@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,339 @@
1
+ /**
2
+ * Passport Service — facade over CRUD, document generation, and audit sub-modules.
3
+ * CRUD operations live here; documents and audit are delegated to sub-modules.
4
+ */
5
+ import { writeFile, readFile, readdir, mkdir, stat } from 'node:fs/promises';
6
+ import { join, dirname } from 'node:path';
7
+ import { randomUUID } from 'node:crypto';
8
+ import { z } from 'zod';
9
+ import type { ScanContext } from '../ports/scanner.port.js';
10
+ import type { EventBusPort } from '../ports/events.port.js';
11
+ import type { ScanResult } from '../types/common.types.js';
12
+ import type { AgentPassport } from '../types/passport.types.js';
13
+ import { parsePassport } from '../types/passport-schemas.js';
14
+ import { createEvidence } from '../domain/scanner/evidence.js';
15
+ import type { Scanner } from '../domain/scanner/create-scanner.js';
16
+ import { parseDepsFromContext } from '../domain/shared/parse-dependencies.js';
17
+ import { runLayer3 } from '../domain/scanner/layers/layer3-config.js';
18
+ import { runLayer4 } from '../domain/scanner/layers/layer4-patterns.js';
19
+ import { discoverAgents } from '../domain/passport/discovery/agent-discovery.js';
20
+ import { analyzeAutonomy } from '../domain/passport/discovery/autonomy-analyzer.js';
21
+ import type { AutonomyAnalysis } from '../domain/passport/discovery/autonomy-analyzer.js';
22
+ import { scanPermissions } from '../domain/passport/discovery/permission-scanner.js';
23
+ import { buildPassport } from '../domain/passport/builder/manifest-builder.js';
24
+ import type { ProjectProfile } from '../domain/passport/builder/manifest-builder.js';
25
+ import { deriveDocStatusFromFindings, buildScanSummary, buildDocQualitySummary } from '../domain/passport/scan-to-compliance.js';
26
+ import { loadOrCreateKeyPair, signPassport, verifyPassport as verifyPassportCrypto } from '../domain/passport/crypto-signer.js';
27
+ import { validatePassport, computeCompleteness } from '../domain/passport/passport-validator.js';
28
+ import type { ValidationResult, CompletenessResult } from '../domain/passport/passport-validator.js';
29
+ import type { EvidenceStore } from '../domain/scanner/evidence-store.js';
30
+ import type { AuditStore } from '../domain/audit/audit-trail.js';
31
+ import { updatePassportCompliance } from './passport-service-utils.js';
32
+ import { createLogger } from '../infra/logger.js';
33
+
34
+ const log = createLogger('passport-service');
35
+ import { createPassportDocuments } from './passport-documents.js';
36
+ import { createPassportAudit } from './passport-audit.js';
37
+
38
+ // --- Types ---
39
+
40
+ export interface PassportServiceDeps {
41
+ readonly collectFiles: (path: string) => Promise<ScanContext>;
42
+ readonly scanner: Scanner;
43
+ readonly events: EventBusPort;
44
+ readonly getProjectPath: () => string;
45
+ readonly getLastScanResult: () => ScanResult | null;
46
+ readonly loadTemplate?: (file: string) => Promise<string>;
47
+ readonly loadPolicyTemplate?: (file: string) => Promise<string>;
48
+ readonly evidenceStore?: EvidenceStore;
49
+ readonly auditStore?: AuditStore;
50
+ }
51
+
52
+ export interface InitPassportResult {
53
+ readonly manifests: readonly AgentPassport[];
54
+ readonly savedPaths: readonly string[];
55
+ readonly skipped: readonly string[];
56
+ }
57
+
58
+ // --- Helpers ---
59
+
60
+ /** Read .complior/profile.json — non-fatal if missing. */
61
+ const ProfileSchema = z.record(z.unknown());
62
+
63
+ const loadProjectProfile = async (projectPath: string): Promise<ProjectProfile | undefined> => {
64
+ try {
65
+ const raw = await readFile(join(projectPath, '.complior', 'profile.json'), 'utf-8');
66
+ const parsed = ProfileSchema.safeParse(JSON.parse(raw));
67
+ if (!parsed.success) { log.warn('Invalid profile.json:', parsed.error.message); return undefined; }
68
+ const profile = parsed.data;
69
+ const business = profile.business as Record<string, unknown> | undefined;
70
+ const data = profile.data as Record<string, unknown> | undefined;
71
+ const aiSystem = profile.aiSystem as Record<string, unknown> | undefined;
72
+ const computed = profile.computed as Record<string, unknown> | undefined;
73
+
74
+ const domain = (business?.domain as string) ?? 'general';
75
+ const dataTypes = Array.isArray(data?.types) ? (data.types as string[]) : [];
76
+ const systemType = (aiSystem?.type as string) ?? 'feature';
77
+ const riskLevel = (computed?.riskLevel as string) ?? 'limited';
78
+ const dataStorage = (data?.storage as string) ?? undefined;
79
+
80
+ return { domain, dataTypes, systemType, riskLevel, dataStorage };
81
+ } catch (err) {
82
+ log.debug('No project profile found:', err);
83
+ return undefined;
84
+ }
85
+ };
86
+
87
+ // --- Service factory ---
88
+
89
+ export const createPassportService = (deps: PassportServiceDeps) => {
90
+ const { collectFiles, events, getProjectPath, getLastScanResult } = deps;
91
+
92
+ // --- CRUD ---
93
+
94
+ const initPassport = async (
95
+ projectPath?: string,
96
+ overrides?: Record<string, unknown>,
97
+ force?: boolean,
98
+ ): Promise<InitPassportResult> => {
99
+ const path = projectPath ?? getProjectPath();
100
+ const ctx = await collectFiles(path);
101
+ const parsedDeps = parseDepsFromContext(ctx);
102
+ const agents = discoverAgents(ctx, parsedDeps);
103
+
104
+ if (agents.length === 0) return { manifests: [], savedPaths: [], skipped: [] };
105
+
106
+ const l3Results = runLayer3(ctx);
107
+ const l4Results = runLayer4(ctx, l3Results);
108
+ const scanResult = getLastScanResult();
109
+
110
+ // Load project profile for risk classification (non-fatal if missing)
111
+ const projectProfile = await loadProjectProfile(path);
112
+
113
+ const manifests: AgentPassport[] = [];
114
+ const savedPaths: string[] = [];
115
+ const skipped: string[] = [];
116
+
117
+ for (const agent of agents) {
118
+ const autonomy = analyzeAutonomy(l4Results);
119
+ const permissions = scanPermissions(ctx);
120
+
121
+ // Check for existing passport to preserve dates on --force
122
+ const agentsDir = join(path, '.complior', 'agents');
123
+ const filePath = join(agentsDir, `${agent.name}-manifest.json`);
124
+ let existingPassport: { created: string; deployed_since: string } | undefined;
125
+
126
+ if (force) {
127
+ try {
128
+ const raw = await readFile(filePath, 'utf-8');
129
+ const existing = parsePassport(raw);
130
+ if (existing) {
131
+ existingPassport = {
132
+ created: existing.created,
133
+ deployed_since: existing.lifecycle.deployed_since,
134
+ };
135
+ }
136
+ } catch (err) { log.debug(`No existing passport for ${agent.name}:`, err); }
137
+ }
138
+
139
+ const unsignedManifest = buildPassport({
140
+ agent, autonomy, permissions,
141
+ scanResult: scanResult ?? undefined,
142
+ overrides,
143
+ projectProfile,
144
+ existingPassport,
145
+ });
146
+
147
+ const keyPair = await loadOrCreateKeyPair();
148
+ const signature = signPassport(unsignedManifest, keyPair.privateKey);
149
+ const signedManifest: AgentPassport = { ...unsignedManifest, signature };
150
+
151
+ await mkdir(dirname(filePath), { recursive: true });
152
+
153
+ if (!force) {
154
+ try {
155
+ const existing = await readFile(filePath, 'utf-8');
156
+ if (existing.trim().length > 0) { skipped.push(agent.name); continue; }
157
+ // Empty file — treat as non-existent, overwrite
158
+ } catch { /* file doesn't exist — create it */ }
159
+ }
160
+
161
+ await writeFile(filePath, JSON.stringify(signedManifest, null, 2));
162
+ manifests.push(signedManifest);
163
+ savedPaths.push(filePath);
164
+
165
+ if (deps.auditStore) {
166
+ await deps.auditStore.append('passport.created', { name: agent.name, path: filePath }, agent.name);
167
+ }
168
+ if (deps.evidenceStore) {
169
+ const evidence = createEvidence(agent.name, 'passport', 'passport', { file: filePath });
170
+ await deps.evidenceStore.append([evidence], randomUUID());
171
+ }
172
+ if (scanResult) {
173
+ events.emit('agent.scan.completed', { agentName: agent.name, result: scanResult });
174
+ events.emit('agent.score.updated', { agentName: agent.name, before: 0, after: scanResult.score?.totalScore ?? 0 });
175
+ }
176
+ }
177
+
178
+ events.emit('scan.started', { projectPath: path });
179
+ return { manifests, savedPaths, skipped };
180
+ };
181
+
182
+ const listPassports = async (projectPath?: string): Promise<readonly AgentPassport[]> => {
183
+ const path = projectPath ?? getProjectPath();
184
+ const agentsDir = join(path, '.complior', 'agents');
185
+ try {
186
+ const files = await readdir(agentsDir);
187
+ const manifests: AgentPassport[] = [];
188
+ for (const file of files) {
189
+ if (!file.endsWith('-manifest.json')) continue;
190
+ const content = await readFile(join(agentsDir, file), 'utf-8');
191
+ const passport = parsePassport(content);
192
+ if (passport) manifests.push(passport);
193
+ }
194
+ return manifests;
195
+ } catch (err) { log.debug('Failed to list passports:', err); return []; }
196
+ };
197
+
198
+ const showPassport = async (name: string, projectPath?: string): Promise<AgentPassport | null> => {
199
+ const path = projectPath ?? getProjectPath();
200
+ try {
201
+ const content = await readFile(join(path, '.complior', 'agents', `${name}-manifest.json`), 'utf-8');
202
+ return parsePassport(content);
203
+ } catch (err) { log.debug(`Failed to read passport ${name}:`, err); return null; }
204
+ };
205
+
206
+ const verifyPassport = async (name: string, projectPath?: string): Promise<boolean> => {
207
+ const manifest = await showPassport(name, projectPath);
208
+ if (manifest === null) return false;
209
+ return verifyPassportCrypto(manifest);
210
+ };
211
+
212
+ const analyzeProjectAutonomy = async (projectPath?: string): Promise<AutonomyAnalysis> => {
213
+ const path = projectPath ?? getProjectPath();
214
+ const ctx = await collectFiles(path);
215
+ return analyzeAutonomy(runLayer4(ctx, runLayer3(ctx)));
216
+ };
217
+
218
+ const validatePassportByName = async (name: string, projectPath?: string): Promise<ValidationResult | null> => {
219
+ const manifest = await showPassport(name, projectPath);
220
+ return manifest ? validatePassport(manifest) : null;
221
+ };
222
+
223
+ const getPassportCompleteness = async (name: string, projectPath?: string): Promise<CompletenessResult | null> => {
224
+ const manifest = await showPassport(name, projectPath);
225
+ return manifest ? computeCompleteness(manifest) : null;
226
+ };
227
+
228
+ const findAgentsForFile = async (changedPath: string): Promise<readonly { name: string; sourceFiles: readonly string[] }[]> => {
229
+ const { relative } = await import('node:path');
230
+ const projectPath = getProjectPath();
231
+ const relChanged = relative(projectPath, changedPath);
232
+ const passports = await listPassports(projectPath);
233
+ return passports
234
+ .filter((p) => (p.source_files ?? []).some((sf) => relChanged === sf || relChanged.startsWith(sf + '/')))
235
+ .map((p) => ({ name: p.name, sourceFiles: p.source_files ?? [] }));
236
+ };
237
+
238
+ /** Step 10: Auto-update passports after scan — refreshes score, doc status, and scan_summary per-agent. */
239
+ const updatePassportsAfterScan = async (scanResult: ScanResult, projectPath?: string): Promise<void> => {
240
+ const path = projectPath ?? getProjectPath();
241
+ const passports = await listPassports(path);
242
+
243
+ // Global findings (no agentId) apply to ALL agents — they represent project-wide checks
244
+ // (doc quality, config, dependencies, etc.) that affect every agent in the project.
245
+ const globalFindings = scanResult.findings.filter(f => !f.agentId);
246
+
247
+ for (const passport of passports) {
248
+ // Agent-specific + global findings = full compliance picture for this agent
249
+ const agentSpecificFindings = scanResult.findings.filter(f => f.agentId === passport.name);
250
+ const allAgentFindings = [...agentSpecificFindings, ...globalFindings];
251
+
252
+ const docStatus = deriveDocStatusFromFindings(allAgentFindings, scanResult.scannedAt);
253
+ const scanSummary = buildScanSummary(allAgentFindings, scanResult.scannedAt);
254
+
255
+ // complior_score: per-agent simple ratio (no category weights).
256
+ // Contrast with project_score (weighted 8-category score from score-calculator.ts).
257
+ const agentPassed = allAgentFindings.filter(f => f.type === 'pass').length;
258
+ const agentFailed = allAgentFindings.filter(f => f.type === 'fail').length;
259
+ const applicable = agentPassed + agentFailed;
260
+ const agentScore = applicable > 0 ? Math.round((agentPassed / applicable) * 100) : 0;
261
+
262
+ const docQualitySummary = buildDocQualitySummary(docStatus);
263
+
264
+ await updatePassportCompliance(deps, passport.name, {
265
+ complior_score: agentScore,
266
+ project_score: scanResult.score.totalScore,
267
+ last_scan: scanResult.scannedAt,
268
+ scan_summary: scanSummary,
269
+ doc_quality_summary: docQualitySummary,
270
+ ...docStatus,
271
+ }, path).catch((err) => { log.debug(`Failed to update passport ${passport.name}:`, err); });
272
+ }
273
+ };
274
+
275
+ // --- Delegate to sub-modules ---
276
+
277
+ const coreOps = { showPassport, listPassports };
278
+ const docs = createPassportDocuments(deps, coreOps);
279
+ const audit = createPassportAudit(deps, coreOps);
280
+
281
+ /** Rename a passport: update file name, internal name field, re-sign. */
282
+ const renamePassport = async (
283
+ oldName: string,
284
+ newName: string,
285
+ projectPath?: string,
286
+ ): Promise<{ oldPath: string; newPath: string }> => {
287
+ const path = projectPath ?? getProjectPath();
288
+ const agentsDir = join(path, '.complior', 'agents');
289
+ const oldPath = join(agentsDir, `${oldName}-manifest.json`);
290
+ const newPath = join(agentsDir, `${newName}-manifest.json`);
291
+
292
+ // Read existing passport
293
+ const raw = await readFile(oldPath, 'utf-8');
294
+ const passport = parsePassport(raw);
295
+ if (!passport) throw new Error(`Invalid passport: ${oldName}`);
296
+
297
+ // Check target doesn't already exist
298
+ try { await stat(newPath); throw new Error(`Passport '${newName}' already exists`); } catch (e) {
299
+ if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e;
300
+ }
301
+
302
+ // Update name + re-sign
303
+ const updated: AgentPassport = { ...passport, name: newName, updated: new Date().toISOString() };
304
+ const keyPair = await loadOrCreateKeyPair();
305
+ const signature = signPassport(updated, keyPair.privateKey);
306
+ const signed: AgentPassport = { ...updated, signature };
307
+
308
+ // Write new file, remove old
309
+ await writeFile(newPath, JSON.stringify(signed, null, 2));
310
+ const { unlink } = await import('node:fs/promises');
311
+ await unlink(oldPath);
312
+
313
+ // Audit trail
314
+ if (deps.auditStore) {
315
+ await deps.auditStore.append('passport.updated' as Parameters<typeof deps.auditStore.append>[0], {
316
+ action: 'rename', oldName, newName, path: newPath,
317
+ }, newName);
318
+ }
319
+
320
+ return { oldPath, newPath };
321
+ };
322
+
323
+ return Object.freeze({
324
+ initPassport,
325
+ listPassports,
326
+ showPassport,
327
+ verifyPassport,
328
+ analyzeProjectAutonomy,
329
+ validatePassportByName,
330
+ getPassportCompleteness,
331
+ findAgentsForFile,
332
+ updatePassportsAfterScan,
333
+ renamePassport,
334
+ ...docs,
335
+ ...audit,
336
+ });
337
+ };
338
+
339
+ export type PassportService = ReturnType<typeof createPassportService>;
@@ -0,0 +1,81 @@
1
+ import type { ProxyConfig, ProxyStats, McpCallLog } from '../domain/proxy/proxy-types.js';
2
+ import { ProxyConfigSchema } from '../domain/proxy/proxy-types.js';
3
+ import { createInterceptor, type ProxyInterceptor, type InterceptorDeps } from '../domain/proxy/proxy-interceptor.js';
4
+ import { createProxyBridge, type ProxyBridge } from '../domain/proxy/proxy-bridge.js';
5
+ import { createPolicyEngine, type ProxyPolicy } from '../domain/proxy/policy-engine.js';
6
+
7
+ export interface ProxyServiceDeps {
8
+ readonly logCall?: InterceptorDeps['logCall'];
9
+ readonly recordEvidence?: InterceptorDeps['recordEvidence'];
10
+ readonly loadPolicy?: (projectPath: string) => Promise<ProxyPolicy | null>;
11
+ }
12
+
13
+ export interface ProxyService {
14
+ readonly start: (config: ProxyConfig, projectPath?: string) => Promise<{ success: boolean; error?: string }>;
15
+ readonly stop: () => { success: boolean };
16
+ readonly health: () => ProxyStats | { isRunning: false };
17
+ readonly getCallLog: () => readonly McpCallLog[];
18
+ }
19
+
20
+ export const createProxyService = (deps: ProxyServiceDeps): ProxyService => {
21
+ let bridge: ProxyBridge | null = null;
22
+ let interceptor: ProxyInterceptor | null = null;
23
+
24
+ const start = async (rawConfig: ProxyConfig, projectPath?: string): Promise<{ success: boolean; error?: string }> => {
25
+ if (bridge?.isRunning()) {
26
+ return { success: false, error: 'Proxy is already running' };
27
+ }
28
+
29
+ const parsed = ProxyConfigSchema.safeParse(rawConfig);
30
+ if (!parsed.success) {
31
+ return { success: false, error: `Invalid config: ${parsed.error.message}` };
32
+ }
33
+ const config = parsed.data;
34
+
35
+ // Load policy from project path if available
36
+ let policyEngine: ReturnType<typeof createPolicyEngine> | undefined;
37
+ if (deps.loadPolicy && projectPath) {
38
+ try {
39
+ const policy = await deps.loadPolicy(projectPath);
40
+ if (policy) {
41
+ policyEngine = createPolicyEngine(policy);
42
+ }
43
+ } catch {
44
+ // Policy loading failed — continue without policy (allow-all)
45
+ }
46
+ }
47
+
48
+ const startedAt = new Date().toISOString();
49
+ interceptor = createInterceptor(
50
+ { logCall: deps.logCall, recordEvidence: deps.recordEvidence, policyEngine },
51
+ startedAt,
52
+ );
53
+ bridge = createProxyBridge(config, interceptor);
54
+
55
+ try {
56
+ await bridge.start();
57
+ return { success: true };
58
+ } catch (err) {
59
+ return { success: false, error: `Failed to start proxy: ${err instanceof Error ? err.message : String(err)}` };
60
+ }
61
+ };
62
+
63
+ const stop = (): { success: boolean } => {
64
+ if (!bridge?.isRunning()) {
65
+ return { success: false };
66
+ }
67
+ bridge.stop();
68
+ return { success: true };
69
+ };
70
+
71
+ const health = (): ProxyStats | { isRunning: false } => {
72
+ if (!interceptor || !bridge?.isRunning()) {
73
+ return { isRunning: false };
74
+ }
75
+ return interceptor.getStats();
76
+ };
77
+
78
+ const getCallLog = () => interceptor?.getCallLog() ?? [];
79
+
80
+ return Object.freeze({ start, stop, health, getCallLog });
81
+ };
@@ -0,0 +1,72 @@
1
+ import { resolve } from 'node:path';
2
+ import type { ScanResult } from '../types/common.types.js';
3
+ import type { EventBusPort } from '../ports/events.port.js';
4
+ import { buildAuditReportData } from '../domain/reporter/audit-report.js';
5
+ import { renderPdfReport } from '../domain/reporter/pdf-renderer.js';
6
+ import { generateComplianceMd } from '../domain/reporter/compliance-md.js';
7
+
8
+ export interface ReportServiceDeps {
9
+ readonly events: EventBusPort;
10
+ readonly getProjectPath: () => string;
11
+ readonly getLastScanResult: () => ScanResult | null;
12
+ readonly getVersion: () => string;
13
+ }
14
+
15
+ export const createReportService = (deps: ReportServiceDeps) => {
16
+ const { events, getProjectPath, getLastScanResult, getVersion } = deps;
17
+
18
+ const generatePdf = async (options?: {
19
+ readonly organization?: string;
20
+ readonly jurisdiction?: string;
21
+ readonly outputPath?: string;
22
+ readonly isFree?: boolean;
23
+ }): Promise<{ path: string; pages: number }> => {
24
+ const scanResult = getLastScanResult();
25
+ if (!scanResult) {
26
+ throw new Error('No scan result available. Run a scan first.');
27
+ }
28
+
29
+ const data = buildAuditReportData(scanResult, {
30
+ organization: options?.organization,
31
+ jurisdiction: options?.jurisdiction,
32
+ version: getVersion(),
33
+ });
34
+
35
+ const outputPath = options?.outputPath ?? resolve(
36
+ getProjectPath(), '.complior', 'reports', `audit-report-${Date.now()}.pdf`,
37
+ );
38
+
39
+ await renderPdfReport(data, outputPath, { isFree: options?.isFree });
40
+
41
+ events.emit('report.generated', { path: outputPath, format: 'pdf' });
42
+
43
+ // Approximate page count from findings
44
+ const pages = Math.max(4, Math.ceil(data.findings.length / 8) + 3);
45
+ return { path: outputPath, pages };
46
+ };
47
+
48
+ const generateMarkdown = async (options?: {
49
+ readonly outputPath?: string;
50
+ }): Promise<{ path: string; content: string }> => {
51
+ const scanResult = getLastScanResult();
52
+ if (!scanResult) {
53
+ throw new Error('No scan result available. Run a scan first.');
54
+ }
55
+
56
+ const content = generateComplianceMd(scanResult, getVersion());
57
+ const outputPath = options?.outputPath ?? resolve(getProjectPath(), 'COMPLIANCE.md');
58
+
59
+ const { writeFile, mkdir } = await import('node:fs/promises');
60
+ const { dirname } = await import('node:path');
61
+ await mkdir(dirname(outputPath), { recursive: true });
62
+ await writeFile(outputPath, content);
63
+
64
+ events.emit('report.generated', { path: outputPath, format: 'markdown' });
65
+
66
+ return { path: outputPath, content };
67
+ };
68
+
69
+ return Object.freeze({ generatePdf, generateMarkdown });
70
+ };
71
+
72
+ export type ReportService = ReturnType<typeof createReportService>;