@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,211 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { REGISTRY_CARDS, findRegistryCard, findRegistryCardsByProvider, REGISTRY_SLUG_PATTERN, isGpaiSystemic, getProviderName } from '../../data/registry-cards.js';
3
+ import { analyzeSupplyChain, SUPPLY_CHAIN_OBLIGATIONS } from './dependency-analyzer.js';
4
+ import type { ParsedDependency } from '../scanner/layers/layer3-parsers.js';
5
+
6
+ // --- Registry Cards Tests ---
7
+
8
+ describe('RegistryToolCards', () => {
9
+ it('contains 10 registry cards', () => {
10
+ expect(REGISTRY_CARDS).toHaveLength(10);
11
+ });
12
+
13
+ it('all cards have required fields', () => {
14
+ for (const card of REGISTRY_CARDS) {
15
+ expect(card.slug).toBeTruthy();
16
+ expect(card.name).toBeTruthy();
17
+ expect(card.provider.name).toBeTruthy();
18
+ expect(card.capabilities!.length).toBeGreaterThan(0);
19
+ expect(card.assessments?.['eu-ai-act']?.training_cutoff).toBeTruthy();
20
+ expect(card.assessments?.['eu-ai-act']?.license).toBeTruthy();
21
+ expect(card.assessments?.['eu-ai-act']?.limitations!.length).toBeGreaterThan(0);
22
+ expect(card.assessments?.['eu-ai-act']?.known_risks!.length).toBeGreaterThan(0);
23
+ expect(card.assessments?.['eu-ai-act']?.risk_reasoning).toBeTruthy();
24
+ }
25
+ });
26
+
27
+ it('findRegistryCard returns card by slug', () => {
28
+ const card = findRegistryCard('gpt-4o');
29
+ expect(card).toBeDefined();
30
+ expect(card!.name).toBe('GPT-4o');
31
+ expect(card!.provider.name).toBe('OpenAI');
32
+ });
33
+
34
+ it('findRegistryCard returns undefined for unknown slug', () => {
35
+ expect(findRegistryCard('nonexistent-model')).toBeUndefined();
36
+ });
37
+
38
+ it('findRegistryCardsByProvider filters correctly', () => {
39
+ const anthropicCards = findRegistryCardsByProvider('Anthropic');
40
+ expect(anthropicCards).toHaveLength(2);
41
+ for (const card of anthropicCards) {
42
+ expect(card.provider.name).toBe('Anthropic');
43
+ }
44
+ });
45
+
46
+ it('REGISTRY_SLUG_PATTERN matches known model slugs', () => {
47
+ const text = 'Using gpt-4o and claude-sonnet-4 models';
48
+ const matches = [...text.matchAll(new RegExp(REGISTRY_SLUG_PATTERN.source, 'g'))].map((m) => m[0]);
49
+ expect(matches).toContain('gpt-4o');
50
+ expect(matches).toContain('claude-sonnet-4');
51
+ });
52
+
53
+ it('REGISTRY_SLUG_PATTERN does not false-positive on embedded substrings', () => {
54
+ const text = 'ratio1 protocol1 foo1bar';
55
+ const matches = [...text.matchAll(new RegExp(REGISTRY_SLUG_PATTERN.source, 'g'))];
56
+ expect(matches).toHaveLength(0);
57
+ });
58
+
59
+ it('REGISTRY_SLUG_PATTERN is derived from REGISTRY_CARDS data', () => {
60
+ for (const card of REGISTRY_CARDS) {
61
+ const text = `model: ${card.slug}`;
62
+ const matches = [...text.matchAll(new RegExp(REGISTRY_SLUG_PATTERN.source, 'g'))].map((m) => m[0]);
63
+ expect(matches).toContain(card.slug);
64
+ }
65
+ });
66
+
67
+ it('isGpaiSystemic correctly identifies systemic risk', () => {
68
+ const gpt4o = findRegistryCard('gpt-4o')!;
69
+ expect(isGpaiSystemic(gpt4o)).toBe(true);
70
+
71
+ const gpt4oMini = findRegistryCard('gpt-4o-mini')!;
72
+ expect(isGpaiSystemic(gpt4oMini)).toBe(false);
73
+ });
74
+
75
+ it('getProviderName extracts provider name', () => {
76
+ const card = findRegistryCard('gpt-4o')!;
77
+ expect(getProviderName(card)).toBe('OpenAI');
78
+
79
+ const mistral = findRegistryCard('mistral-large')!;
80
+ expect(getProviderName(mistral)).toBe('Mistral AI');
81
+ });
82
+ });
83
+
84
+ // --- Analyzer Tests ---
85
+
86
+ describe('analyzeSupplyChain', () => {
87
+ it('returns zero risk for empty dependencies', () => {
88
+ const report = analyzeSupplyChain('/test', [], []);
89
+ expect(report.totalDependencies).toBe(0);
90
+ expect(report.aiSdkCount).toBe(0);
91
+ expect(report.bannedCount).toBe(0);
92
+ expect(report.risks).toHaveLength(0);
93
+ expect(report.riskScore).toBe(0);
94
+ });
95
+
96
+ it('detects banned packages as critical risk', () => {
97
+ const deps: ParsedDependency[] = [
98
+ { name: 'clearview-ai', version: '1.0.0', ecosystem: 'npm' },
99
+ ];
100
+ const report = analyzeSupplyChain('/test', deps, []);
101
+ expect(report.bannedCount).toBe(1);
102
+ expect(report.risks.length).toBeGreaterThanOrEqual(1);
103
+ const bannedRisk = report.risks.find((r) => r.type === 'banned-package');
104
+ expect(bannedRisk).toBeDefined();
105
+ expect(bannedRisk!.severity).toBe('critical');
106
+ expect(bannedRisk!.articleRef).toBe('Art.5');
107
+ });
108
+
109
+ it('counts AI SDK packages', () => {
110
+ const deps: ParsedDependency[] = [
111
+ { name: 'openai', version: '4.0.0', ecosystem: 'npm' },
112
+ { name: '@anthropic-ai/sdk', version: '1.0.0', ecosystem: 'npm' },
113
+ { name: 'express', version: '4.18.0', ecosystem: 'npm' },
114
+ ];
115
+ const report = analyzeSupplyChain('/test', deps, []);
116
+ expect(report.aiSdkCount).toBe(2);
117
+ expect(report.totalDependencies).toBe(3);
118
+ });
119
+
120
+ it('flags missing bias testing when AI SDKs present', () => {
121
+ const deps: ParsedDependency[] = [
122
+ { name: 'openai', version: '4.0.0', ecosystem: 'npm' },
123
+ ];
124
+ const report = analyzeSupplyChain('/test', deps, []);
125
+ const biasRisk = report.risks.find((r) => r.type === 'missing-bias-testing');
126
+ expect(biasRisk).toBeDefined();
127
+ expect(biasRisk!.severity).toBe('medium');
128
+ });
129
+
130
+ it('no bias testing warning when bias package present', () => {
131
+ const deps: ParsedDependency[] = [
132
+ { name: 'openai', version: '4.0.0', ecosystem: 'npm' },
133
+ { name: 'fairlearn', version: '0.9.0', ecosystem: 'pip' },
134
+ ];
135
+ const report = analyzeSupplyChain('/test', deps, []);
136
+ const biasRisk = report.risks.find((r) => r.type === 'missing-bias-testing');
137
+ expect(biasRisk).toBeUndefined();
138
+ });
139
+
140
+ it('matches detected models to cards', () => {
141
+ const report = analyzeSupplyChain('/test', [], ['gpt-4o', 'claude-sonnet-4']);
142
+ expect(report.registryCards).toHaveLength(2);
143
+ expect(report.detectedModels).toEqual(['gpt-4o', 'claude-sonnet-4']);
144
+ });
145
+
146
+ it('flags GPAI systemic models as high risk', () => {
147
+ const report = analyzeSupplyChain('/test', [], ['gpt-4o']);
148
+ const systemicRisk = report.risks.find((r) => r.type === 'gpai-systemic');
149
+ expect(systemicRisk).toBeDefined();
150
+ expect(systemicRisk!.severity).toBe('high');
151
+ expect(systemicRisk!.articleRef).toBe('Art.51');
152
+ });
153
+
154
+ it('computes risk score correctly (capped at 100)', () => {
155
+ // 5 banned packages = 5 × 25 = 125 → capped at 100
156
+ const deps: ParsedDependency[] = [
157
+ { name: 'clearview-ai', version: '1.0', ecosystem: 'npm' },
158
+ { name: 'social-credit-score', version: '1.0', ecosystem: 'npm' },
159
+ { name: 'predictive-policing', version: '1.0', ecosystem: 'npm' },
160
+ { name: 'emotion-recognition', version: '1.0', ecosystem: 'npm' },
161
+ { name: 'subliminal-ai', version: '1.0', ecosystem: 'npm' },
162
+ ];
163
+ const report = analyzeSupplyChain('/test', deps, []);
164
+ expect(report.riskScore).toBe(100);
165
+ });
166
+
167
+ it('flags AI SDKs without registry cards', () => {
168
+ const deps: ParsedDependency[] = [
169
+ { name: 'replicate', version: '1.0.0', ecosystem: 'npm' },
170
+ ];
171
+ const report = analyzeSupplyChain('/test', deps, []);
172
+ const noCardRisk = report.risks.find((r) => r.type === 'ai-sdk-no-card');
173
+ expect(noCardRisk).toBeDefined();
174
+ expect(noCardRisk!.severity).toBe('low');
175
+ expect(noCardRisk!.packageName).toBe('replicate');
176
+ });
177
+ });
178
+
179
+ // --- Integration Tests ---
180
+
181
+ describe('SupplyChain integration', () => {
182
+ it('report is frozen', () => {
183
+ const report = analyzeSupplyChain('/test', [], []);
184
+ expect(Object.isFrozen(report)).toBe(true);
185
+ });
186
+
187
+ it('obligation refs include OBL-026', () => {
188
+ const report = analyzeSupplyChain('/test', [], []);
189
+ expect(report.obligationRefs).toContain('OBL-026');
190
+ expect(report.obligationRefs).toContain('OBL-005');
191
+ });
192
+
193
+ it('report has valid structure', () => {
194
+ const deps: ParsedDependency[] = [
195
+ { name: 'openai', version: '4.0.0', ecosystem: 'npm' },
196
+ ];
197
+ const report = analyzeSupplyChain('/test', deps, ['gpt-4o']);
198
+ expect(report.projectPath).toBe('/test');
199
+ expect(report.timestamp).toBeTruthy();
200
+ expect(typeof report.duration).toBe('number');
201
+ expect(report.totalDependencies).toBe(1);
202
+ expect(report.aiSdkCount).toBe(1);
203
+ expect(report.registryCards.length).toBeGreaterThan(0);
204
+ expect(report.riskScore).toBeGreaterThanOrEqual(0);
205
+ expect(report.riskScore).toBeLessThanOrEqual(100);
206
+ });
207
+
208
+ it('SUPPLY_CHAIN_OBLIGATIONS is correct', () => {
209
+ expect(SUPPLY_CHAIN_OBLIGATIONS).toEqual(['OBL-026', 'OBL-005']);
210
+ });
211
+ });
@@ -0,0 +1,32 @@
1
+ import type { RegistryToolCard } from '../../data/registry-cards.js';
2
+
3
+ export type SupplyChainRiskType =
4
+ | 'banned-package'
5
+ | 'ai-sdk-no-card'
6
+ | 'missing-bias-testing'
7
+ | 'gpai-systemic';
8
+
9
+ export interface SupplyChainRisk {
10
+ readonly type: SupplyChainRiskType;
11
+ readonly severity: 'critical' | 'high' | 'medium' | 'low';
12
+ readonly packageName: string;
13
+ readonly packageVersion: string;
14
+ readonly ecosystem: string;
15
+ readonly description: string;
16
+ readonly articleRef: string;
17
+ readonly obligationId: string;
18
+ }
19
+
20
+ export interface SupplyChainReport {
21
+ readonly projectPath: string;
22
+ readonly timestamp: string;
23
+ readonly duration: number;
24
+ readonly totalDependencies: number;
25
+ readonly aiSdkCount: number;
26
+ readonly bannedCount: number;
27
+ readonly risks: readonly SupplyChainRisk[];
28
+ readonly riskScore: number;
29
+ readonly detectedModels: readonly string[];
30
+ readonly registryCards: readonly RegistryToolCard[];
31
+ readonly obligationRefs: readonly string[];
32
+ }
@@ -0,0 +1,187 @@
1
+ import type { OnboardingProfile } from '../../onboarding/profile.js';
2
+
3
+ export interface GeneratedConfig {
4
+ readonly type: 'docker-compose' | 'env' | 'ci-cd';
5
+ readonly filename: string;
6
+ readonly content: string;
7
+ readonly description: string;
8
+ readonly changes: readonly string[];
9
+ }
10
+
11
+ export const generateDockerCompose = (profile: OnboardingProfile): GeneratedConfig => {
12
+ const services: string[] = [];
13
+ const changes: string[] = [];
14
+
15
+ services.push(` app:
16
+ build: .
17
+ ports:
18
+ - "3000:3000"
19
+ environment:
20
+ - AI_DISCLOSURE_ENABLED=true
21
+ - AUDIT_LOG_ENABLED=true
22
+ - COMPLIANCE_MODE=strict
23
+ depends_on:
24
+ - audit-db`);
25
+ changes.push('App service with compliance environment variables');
26
+
27
+ services.push(` audit-db:
28
+ image: postgres:16-alpine
29
+ environment:
30
+ POSTGRES_DB: complior_audit
31
+ POSTGRES_PASSWORD: \${AUDIT_DB_PASSWORD}
32
+ volumes:
33
+ - audit-data:/var/lib/postgresql/data`);
34
+ changes.push('Audit trail database (PostgreSQL)');
35
+
36
+ if (profile.computed.riskLevel === 'high') {
37
+ services.push(` monitoring:
38
+ image: prom/prometheus:latest
39
+ ports:
40
+ - "9090:9090"
41
+ volumes:
42
+ - ./prometheus.yml:/etc/prometheus/prometheus.yml`);
43
+ changes.push('Monitoring service (Prometheus) for high-risk AI');
44
+ }
45
+
46
+ const content = `# Compliance-enhanced Docker Compose
47
+ # Generated by Complior for ${profile.business.domain} domain (${profile.computed.riskLevel} risk)
48
+
49
+ version: "3.9"
50
+
51
+ services:
52
+ ${services.join('\n\n')}
53
+
54
+ volumes:
55
+ audit-data:
56
+ `;
57
+
58
+ return Object.freeze({
59
+ type: 'docker-compose',
60
+ filename: 'docker-compose.compliance.yml',
61
+ content,
62
+ description: `Docker Compose with compliance services for ${profile.computed.riskLevel} risk ${profile.business.domain} project`,
63
+ changes,
64
+ });
65
+ };
66
+
67
+ export const generateEnvExample = (profile: OnboardingProfile): GeneratedConfig => {
68
+ const lines: string[] = [
69
+ '# Compliance Environment Variables',
70
+ `# Generated by Complior for ${profile.business.domain} domain`,
71
+ '',
72
+ '# === AI Disclosure (Art. 50) ===',
73
+ 'AI_DISCLOSURE_ENABLED=true',
74
+ 'AI_DISCLOSURE_TEXT="This service uses artificial intelligence"',
75
+ '',
76
+ '# === Audit Logging (Art. 12) ===',
77
+ 'AUDIT_LOG_ENABLED=true',
78
+ 'AUDIT_LOG_RETENTION_DAYS=365',
79
+ 'AUDIT_DB_PASSWORD=changeme',
80
+ '',
81
+ '# === Human Oversight (Art. 14) ===',
82
+ 'HUMAN_ESCALATION_ENABLED=true',
83
+ 'HUMAN_ESCALATION_THRESHOLD=0.7',
84
+ ];
85
+
86
+ const changes: string[] = ['AI disclosure toggle', 'Audit logging config', 'Human oversight threshold'];
87
+
88
+ if (profile.computed.riskLevel === 'high') {
89
+ lines.push(
90
+ '',
91
+ '# === High-Risk Monitoring (Art. 9) ===',
92
+ 'MONITORING_ENDPOINT=http://localhost:9090',
93
+ 'BIAS_TESTING_ENABLED=true',
94
+ 'BIAS_TESTING_SCHEDULE=weekly',
95
+ );
96
+ changes.push('Monitoring endpoint', 'Bias testing schedule');
97
+ }
98
+
99
+ if (profile.data.types.includes('personal') || profile.data.types.includes('health')) {
100
+ lines.push(
101
+ '',
102
+ '# === Data Protection ===',
103
+ 'DATA_RETENTION_DAYS=90',
104
+ 'DATA_ENCRYPTION_AT_REST=true',
105
+ 'DATA_ANONYMIZATION_ENABLED=true',
106
+ );
107
+ changes.push('Data protection settings');
108
+ }
109
+
110
+ return Object.freeze({
111
+ type: 'env',
112
+ filename: '.env.compliance.example',
113
+ content: lines.join('\n') + '\n',
114
+ description: 'Compliance environment variables with defaults',
115
+ changes,
116
+ });
117
+ };
118
+
119
+ export const generateCIWorkflow = (profile: OnboardingProfile): GeneratedConfig => {
120
+ const changes: string[] = ['Pre-push compliance scan', 'Weekly audit report'];
121
+
122
+ const content = `# Compliance CI/CD Workflow
123
+ # Generated by Complior
124
+
125
+ name: Compliance Check
126
+
127
+ on:
128
+ push:
129
+ branches: [main, develop]
130
+ pull_request:
131
+ branches: [main]
132
+ schedule:
133
+ - cron: '0 9 * * 1' # Weekly Monday 9am
134
+
135
+ jobs:
136
+ compliance-scan:
137
+ runs-on: ubuntu-latest
138
+ steps:
139
+ - uses: actions/checkout@v4
140
+
141
+ - name: Install Complior
142
+ run: npm install -g complior
143
+
144
+ - name: Run Compliance Scan
145
+ run: complior scan --ci --threshold ${profile.computed.riskLevel === 'high' ? 70 : 50} --sarif results.sarif
146
+
147
+ - name: Upload SARIF
148
+ if: always()
149
+ uses: github/codeql-action/upload-sarif@v3
150
+ with:
151
+ sarif_file: results.sarif
152
+
153
+ weekly-audit:
154
+ if: github.event_name == 'schedule'
155
+ runs-on: ubuntu-latest
156
+ steps:
157
+ - uses: actions/checkout@v4
158
+
159
+ - name: Install Complior
160
+ run: npm install -g complior
161
+
162
+ - name: Generate Audit Report
163
+ run: complior scan --ci --json > audit-report.json
164
+
165
+ - name: Upload Report
166
+ uses: actions/upload-artifact@v4
167
+ with:
168
+ name: compliance-audit-\${{ github.run_number }}
169
+ path: audit-report.json
170
+ `;
171
+
172
+ return Object.freeze({
173
+ type: 'ci-cd',
174
+ filename: '.github/workflows/compliance-check.yml',
175
+ content,
176
+ description: 'GitHub Actions workflow for compliance scanning and weekly audits',
177
+ changes,
178
+ });
179
+ };
180
+
181
+ export const generateAllConfigs = (profile: OnboardingProfile): readonly GeneratedConfig[] => {
182
+ return [
183
+ generateDockerCompose(profile),
184
+ generateEnvExample(profile),
185
+ generateCIWorkflow(profile),
186
+ ];
187
+ };
@@ -0,0 +1,6 @@
1
+ export { generateDockerCompose, generateEnvExample, generateCIWorkflow, generateAllConfigs } from './config-fixer.js';
2
+ export type { GeneratedConfig } from './config-fixer.js';
3
+ export { analyzeScenario } from './scenario-engine.js';
4
+ export type { ScenarioType, WhatIfRequest, WhatIfResult } from './scenario-engine.js';
5
+ export { simulateActions } from './simulate-actions.js';
6
+ export type { SimulationAction, SimulationInput, SimulatedActionResult, SimulationResult } from './simulate-actions.js';
@@ -0,0 +1,121 @@
1
+ import type { OnboardingProfile } from '../../onboarding/profile.js';
2
+ import type { ScoreBreakdown } from '../../types/common.types.js';
3
+
4
+ export type ScenarioType = 'jurisdiction' | 'tool' | 'risk_level';
5
+
6
+ export interface WhatIfRequest {
7
+ readonly type: ScenarioType;
8
+ readonly params: Record<string, string>;
9
+ readonly currentProfile: OnboardingProfile;
10
+ readonly currentScore: ScoreBreakdown;
11
+ }
12
+
13
+ export interface WhatIfResult {
14
+ readonly scenario: string;
15
+ readonly scoreDelta: number;
16
+ readonly projectedScore: number;
17
+ readonly newObligations: readonly string[];
18
+ readonly removedObligations: readonly string[];
19
+ readonly effort: {
20
+ readonly estimatedWeeks: number;
21
+ readonly keyTasks: readonly string[];
22
+ };
23
+ readonly recommendation: string;
24
+ }
25
+
26
+ const JURISDICTION_OBLIGATIONS: Record<string, { count: number; names: readonly string[] }> = {
27
+ UK: { count: 17, names: ['UK AI Safety registration', 'DSIT transparency guidance', 'Post-market monitoring (UK)'] },
28
+ US: { count: 8, names: ['State-level disclosure', 'FTC AI guidelines', 'Algorithmic accountability'] },
29
+ 'US-CO': { count: 5, names: ['Colorado SB 205 disclosure', 'High-risk AI notice', 'Impact assessment'] },
30
+ 'US-TX': { count: 4, names: ['Texas TRAIGA disclosure', 'AI inventory', 'Consumer notification'] },
31
+ KR: { count: 6, names: ['Korea AI Basic Act registration', 'Disclosure requirements', 'Risk assessment'] },
32
+ };
33
+
34
+ const TOOL_IMPACTS: Record<string, { scoreDelta: number; obligations: readonly string[] }> = {
35
+ whisper: { scoreDelta: -5, obligations: ['Audio data retention', 'Consent for audio', 'Transcription accuracy'] },
36
+ 'dall-e': { scoreDelta: -8, obligations: ['Art. 50.2 content marking', 'C2PA metadata', 'Deepfake labeling'] },
37
+ elevenlabs: { scoreDelta: -10, obligations: ['Art. 50.4 deepfake disclosure', 'Voice cloning consent', 'Content marking'] },
38
+ stable_diffusion: { scoreDelta: -7, obligations: ['Content marking', 'Model card', 'GPAI transparency'] },
39
+ midjourney: { scoreDelta: -6, obligations: ['Art. 50.2 image marking', 'Watermark', 'Provenance metadata'] },
40
+ };
41
+
42
+ const RISK_LEVEL_CHANGES: Record<string, { scoreDelta: number; addedObligations: number; keyChanges: readonly string[] }> = {
43
+ 'limited_to_high': { scoreDelta: -20, addedObligations: 25, keyChanges: ['Conformity assessment required', 'FRIA mandatory', 'Bias testing', 'QMS documentation', 'Post-market monitoring'] },
44
+ 'minimal_to_limited': { scoreDelta: -10, addedObligations: 12, keyChanges: ['Art. 50 transparency', 'Disclosure to users', 'Content marking'] },
45
+ 'high_to_limited': { scoreDelta: 15, addedObligations: -20, keyChanges: ['Conformity assessment no longer required', 'Reduced documentation', 'Simplified monitoring'] },
46
+ 'limited_to_minimal': { scoreDelta: 8, addedObligations: -10, keyChanges: ['Minimal obligations only', 'No disclosure required'] },
47
+ };
48
+
49
+ export const analyzeScenario = (request: WhatIfRequest): WhatIfResult => {
50
+ const { type, params, currentProfile, currentScore } = request;
51
+ const baseScore = currentScore.totalScore;
52
+
53
+ if (type === 'jurisdiction') {
54
+ const newJurisdiction = params['jurisdiction'] ?? 'UK';
55
+ const impact = JURISDICTION_OBLIGATIONS[newJurisdiction] ?? { count: 5, names: ['Additional local requirements'] };
56
+ const scoreDelta = -Math.round(impact.count * 0.8);
57
+
58
+ return {
59
+ scenario: `Jurisdiction expansion: ${currentProfile.jurisdiction.primary} → ${currentProfile.jurisdiction.primary} + ${newJurisdiction}`,
60
+ scoreDelta,
61
+ projectedScore: Math.max(0, baseScore + scoreDelta),
62
+ newObligations: impact.names,
63
+ removedObligations: [],
64
+ effort: {
65
+ estimatedWeeks: Math.ceil(impact.count / 5),
66
+ keyTasks: impact.names.slice(0, 3),
67
+ },
68
+ recommendation: `Adding ${newJurisdiction} jurisdiction adds ~${impact.count} obligations. Estimated ${Math.ceil(impact.count / 5)} weeks for compliance.`,
69
+ };
70
+ }
71
+
72
+ if (type === 'tool') {
73
+ const toolName = params['tool']?.toLowerCase() ?? '';
74
+ const impact = TOOL_IMPACTS[toolName] ?? { scoreDelta: -3, obligations: ['Review compliance requirements for new tool'] };
75
+
76
+ return {
77
+ scenario: `Add AI tool: ${params['tool'] ?? 'unknown'}`,
78
+ scoreDelta: impact.scoreDelta,
79
+ projectedScore: Math.max(0, baseScore + impact.scoreDelta),
80
+ newObligations: impact.obligations,
81
+ removedObligations: [],
82
+ effort: {
83
+ estimatedWeeks: Math.ceil(impact.obligations.length / 2),
84
+ keyTasks: impact.obligations.slice(0, 3),
85
+ },
86
+ recommendation: `Adding ${params['tool'] ?? 'this tool'} requires ${impact.obligations.length} additional compliance measures.`,
87
+ };
88
+ }
89
+
90
+ if (type === 'risk_level') {
91
+ const from = currentProfile.computed.riskLevel;
92
+ const to = params['level'] ?? 'high';
93
+ const key = `${from}_to_${to}`;
94
+ const impact = RISK_LEVEL_CHANGES[key] ?? { scoreDelta: -10, addedObligations: 10, keyChanges: ['Review all obligations for new risk level'] };
95
+
96
+ return {
97
+ scenario: `Risk level change: ${from} → ${to}`,
98
+ scoreDelta: impact.scoreDelta,
99
+ projectedScore: Math.max(0, Math.min(100, baseScore + impact.scoreDelta)),
100
+ newObligations: impact.keyChanges.filter((_, i) => impact.addedObligations > 0 ? true : i >= Math.abs(impact.addedObligations)),
101
+ removedObligations: impact.addedObligations < 0 ? impact.keyChanges.slice(0, Math.abs(impact.addedObligations)) : [],
102
+ effort: {
103
+ estimatedWeeks: Math.abs(impact.addedObligations) > 15 ? 6 : 3,
104
+ keyTasks: impact.keyChanges.slice(0, 3),
105
+ },
106
+ recommendation: impact.scoreDelta < 0
107
+ ? `Upgrading to ${to} risk adds ${Math.abs(impact.addedObligations)} obligations. Score impact: ${impact.scoreDelta} points.`
108
+ : `Downgrading to ${to} risk removes ${Math.abs(impact.addedObligations)} obligations. Score improvement: +${impact.scoreDelta} points.`,
109
+ };
110
+ }
111
+
112
+ return {
113
+ scenario: 'Unknown scenario type',
114
+ scoreDelta: 0,
115
+ projectedScore: baseScore,
116
+ newObligations: [],
117
+ removedObligations: [],
118
+ effort: { estimatedWeeks: 0, keyTasks: [] },
119
+ recommendation: 'Unknown scenario type. Use "jurisdiction", "tool", or "risk_level".',
120
+ };
121
+ };