@open-mercato/core 0.6.8-develop.6925.1.cefa200fa4 → 0.6.8-develop.6930.1.1e5976efc3

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 (402) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/eudr_due_diligence_statement/index.js +47 -0
  3. package/dist/generated/entities/eudr_due_diligence_statement/index.js.map +7 -0
  4. package/dist/generated/entities/eudr_evidence_submission/index.js +51 -0
  5. package/dist/generated/entities/eudr_evidence_submission/index.js.map +7 -0
  6. package/dist/generated/entities/eudr_mitigation_action/index.js +31 -0
  7. package/dist/generated/entities/eudr_mitigation_action/index.js.map +7 -0
  8. package/dist/generated/entities/eudr_plot/index.js +39 -0
  9. package/dist/generated/entities/eudr_plot/index.js.map +7 -0
  10. package/dist/generated/entities/eudr_product_mapping/index.js +31 -0
  11. package/dist/generated/entities/eudr_product_mapping/index.js.map +7 -0
  12. package/dist/generated/entities/eudr_risk_assessment/index.js +35 -0
  13. package/dist/generated/entities/eudr_risk_assessment/index.js.map +7 -0
  14. package/dist/generated/entities.ids.generated.js +9 -0
  15. package/dist/generated/entities.ids.generated.js.map +2 -2
  16. package/dist/generated/entity-fields-registry.js +120 -0
  17. package/dist/generated/entity-fields-registry.js.map +2 -2
  18. package/dist/modules/attachments/fields/attachment.js +5 -1
  19. package/dist/modules/attachments/fields/attachment.js.map +2 -2
  20. package/dist/modules/attachments/lib/crud.js +3 -1
  21. package/dist/modules/attachments/lib/crud.js.map +2 -2
  22. package/dist/modules/eudr/acl.js +43 -0
  23. package/dist/modules/eudr/acl.js.map +7 -0
  24. package/dist/modules/eudr/ai-agents.js +205 -0
  25. package/dist/modules/eudr/ai-agents.js.map +7 -0
  26. package/dist/modules/eudr/ai-tools/compliance-pack.js +495 -0
  27. package/dist/modules/eudr/ai-tools/compliance-pack.js.map +7 -0
  28. package/dist/modules/eudr/ai-tools/types.js +10 -0
  29. package/dist/modules/eudr/ai-tools/types.js.map +7 -0
  30. package/dist/modules/eudr/ai-tools.js +10 -0
  31. package/dist/modules/eudr/ai-tools.js.map +7 -0
  32. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +386 -0
  33. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +7 -0
  34. package/dist/modules/eudr/api/evidence-submissions/route.js +318 -0
  35. package/dist/modules/eudr/api/evidence-submissions/route.js.map +7 -0
  36. package/dist/modules/eudr/api/mitigation-actions/route.js +249 -0
  37. package/dist/modules/eudr/api/mitigation-actions/route.js.map +7 -0
  38. package/dist/modules/eudr/api/openapi.js +27 -0
  39. package/dist/modules/eudr/api/openapi.js.map +7 -0
  40. package/dist/modules/eudr/api/plots/import/route.js +294 -0
  41. package/dist/modules/eudr/api/plots/import/route.js.map +7 -0
  42. package/dist/modules/eudr/api/plots/route.js +279 -0
  43. package/dist/modules/eudr/api/plots/route.js.map +7 -0
  44. package/dist/modules/eudr/api/product-mappings/route.js +257 -0
  45. package/dist/modules/eudr/api/product-mappings/route.js.map +7 -0
  46. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +298 -0
  47. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +7 -0
  48. package/dist/modules/eudr/api/product-mappings/suggestions/route.js +132 -0
  49. package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +7 -0
  50. package/dist/modules/eudr/api/reports/annual/route.js +266 -0
  51. package/dist/modules/eudr/api/reports/annual/route.js.map +7 -0
  52. package/dist/modules/eudr/api/risk-assessments/route.js +300 -0
  53. package/dist/modules/eudr/api/risk-assessments/route.js.map +7 -0
  54. package/dist/modules/eudr/api/statements/[id]/export/route.js +631 -0
  55. package/dist/modules/eudr/api/statements/[id]/export/route.js.map +7 -0
  56. package/dist/modules/eudr/api/statements/[id]/readiness/route.js +111 -0
  57. package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +7 -0
  58. package/dist/modules/eudr/api/statements/route.js +314 -0
  59. package/dist/modules/eudr/api/statements/route.js.map +7 -0
  60. package/dist/modules/eudr/api/suppliers/compliance/route.js +173 -0
  61. package/dist/modules/eudr/api/suppliers/compliance/route.js.map +7 -0
  62. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js +468 -0
  63. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js.map +7 -0
  64. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js +16 -0
  65. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js.map +7 -0
  66. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js +351 -0
  67. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js.map +7 -0
  68. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js +17 -0
  69. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js.map +7 -0
  70. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +313 -0
  71. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +7 -0
  72. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js +16 -0
  73. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js.map +7 -0
  74. package/dist/modules/eudr/backend/eudr/page.js +360 -0
  75. package/dist/modules/eudr/backend/eudr/page.js.map +7 -0
  76. package/dist/modules/eudr/backend/eudr/page.meta.js +16 -0
  77. package/dist/modules/eudr/backend/eudr/page.meta.js.map +7 -0
  78. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js +346 -0
  79. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js.map +7 -0
  80. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js +16 -0
  81. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js.map +7 -0
  82. package/dist/modules/eudr/backend/eudr/plots/create/page.js +253 -0
  83. package/dist/modules/eudr/backend/eudr/plots/create/page.js.map +7 -0
  84. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js +17 -0
  85. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js.map +7 -0
  86. package/dist/modules/eudr/backend/eudr/plots/page.js +386 -0
  87. package/dist/modules/eudr/backend/eudr/plots/page.js.map +7 -0
  88. package/dist/modules/eudr/backend/eudr/plots/page.meta.js +16 -0
  89. package/dist/modules/eudr/backend/eudr/plots/page.meta.js.map +7 -0
  90. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js +253 -0
  91. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js.map +7 -0
  92. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js +16 -0
  93. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js.map +7 -0
  94. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js +174 -0
  95. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js.map +7 -0
  96. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js +17 -0
  97. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js.map +7 -0
  98. package/dist/modules/eudr/backend/eudr/product-mappings/page.js +306 -0
  99. package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +7 -0
  100. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js +16 -0
  101. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js.map +7 -0
  102. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js +335 -0
  103. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js.map +7 -0
  104. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js +16 -0
  105. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js.map +7 -0
  106. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js +220 -0
  107. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js.map +7 -0
  108. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js +17 -0
  109. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js.map +7 -0
  110. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +324 -0
  111. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +7 -0
  112. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js +16 -0
  113. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js.map +7 -0
  114. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js +648 -0
  115. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js.map +7 -0
  116. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js +16 -0
  117. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js.map +7 -0
  118. package/dist/modules/eudr/backend/eudr/statements/create/page.js +432 -0
  119. package/dist/modules/eudr/backend/eudr/statements/create/page.js.map +7 -0
  120. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js +17 -0
  121. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js.map +7 -0
  122. package/dist/modules/eudr/backend/eudr/statements/page.js +309 -0
  123. package/dist/modules/eudr/backend/eudr/statements/page.js.map +7 -0
  124. package/dist/modules/eudr/backend/eudr/statements/page.meta.js +16 -0
  125. package/dist/modules/eudr/backend/eudr/statements/page.meta.js.map +7 -0
  126. package/dist/modules/eudr/ce.js +56 -0
  127. package/dist/modules/eudr/ce.js.map +7 -0
  128. package/dist/modules/eudr/commands/evidence-submissions.js +571 -0
  129. package/dist/modules/eudr/commands/evidence-submissions.js.map +7 -0
  130. package/dist/modules/eudr/commands/index.js +7 -0
  131. package/dist/modules/eudr/commands/index.js.map +7 -0
  132. package/dist/modules/eudr/commands/lifecycle-events.js +19 -0
  133. package/dist/modules/eudr/commands/lifecycle-events.js.map +7 -0
  134. package/dist/modules/eudr/commands/mitigation-actions.js +488 -0
  135. package/dist/modules/eudr/commands/mitigation-actions.js.map +7 -0
  136. package/dist/modules/eudr/commands/plots.js +517 -0
  137. package/dist/modules/eudr/commands/plots.js.map +7 -0
  138. package/dist/modules/eudr/commands/product-mappings.js +468 -0
  139. package/dist/modules/eudr/commands/product-mappings.js.map +7 -0
  140. package/dist/modules/eudr/commands/risk-assessments.js +599 -0
  141. package/dist/modules/eudr/commands/risk-assessments.js.map +7 -0
  142. package/dist/modules/eudr/commands/statements.js +747 -0
  143. package/dist/modules/eudr/commands/statements.js.map +7 -0
  144. package/dist/modules/eudr/components/CountrySelectField.js +64 -0
  145. package/dist/modules/eudr/components/CountrySelectField.js.map +7 -0
  146. package/dist/modules/eudr/components/GeometryInput.js +133 -0
  147. package/dist/modules/eudr/components/GeometryInput.js.map +7 -0
  148. package/dist/modules/eudr/components/MappingSuggestionsDialog.js +307 -0
  149. package/dist/modules/eudr/components/MappingSuggestionsDialog.js.map +7 -0
  150. package/dist/modules/eudr/components/MitigationActionsSection.js +345 -0
  151. package/dist/modules/eudr/components/MitigationActionsSection.js.map +7 -0
  152. package/dist/modules/eudr/components/OrderSelectField.js +88 -0
  153. package/dist/modules/eudr/components/OrderSelectField.js.map +7 -0
  154. package/dist/modules/eudr/components/PlotImportDialog.js +229 -0
  155. package/dist/modules/eudr/components/PlotImportDialog.js.map +7 -0
  156. package/dist/modules/eudr/components/PlotMapPreview.js +35 -0
  157. package/dist/modules/eudr/components/PlotMapPreview.js.map +7 -0
  158. package/dist/modules/eudr/components/PlotMapPreviewImpl.js +97 -0
  159. package/dist/modules/eudr/components/PlotMapPreviewImpl.js.map +7 -0
  160. package/dist/modules/eudr/components/PlotMultiSelectField.js +198 -0
  161. package/dist/modules/eudr/components/PlotMultiSelectField.js.map +7 -0
  162. package/dist/modules/eudr/components/RiskCriteriaField.js +128 -0
  163. package/dist/modules/eudr/components/RiskCriteriaField.js.map +7 -0
  164. package/dist/modules/eudr/components/StatementLifecycleBar.js +274 -0
  165. package/dist/modules/eudr/components/StatementLifecycleBar.js.map +7 -0
  166. package/dist/modules/eudr/components/StatementReadinessChecklist.js +56 -0
  167. package/dist/modules/eudr/components/StatementReadinessChecklist.js.map +7 -0
  168. package/dist/modules/eudr/components/StatementRiskSection.js +179 -0
  169. package/dist/modules/eudr/components/StatementRiskSection.js.map +7 -0
  170. package/dist/modules/eudr/components/crudErrorI18n.js +31 -0
  171. package/dist/modules/eudr/components/crudErrorI18n.js.map +7 -0
  172. package/dist/modules/eudr/components/formConfig.js +593 -0
  173. package/dist/modules/eudr/components/formConfig.js.map +7 -0
  174. package/dist/modules/eudr/components/plotForm.js +68 -0
  175. package/dist/modules/eudr/components/plotForm.js.map +7 -0
  176. package/dist/modules/eudr/data/enrichers.js +62 -0
  177. package/dist/modules/eudr/data/enrichers.js.map +7 -0
  178. package/dist/modules/eudr/data/entities.js +437 -0
  179. package/dist/modules/eudr/data/entities.js.map +7 -0
  180. package/dist/modules/eudr/data/validators.js +271 -0
  181. package/dist/modules/eudr/data/validators.js.map +7 -0
  182. package/dist/modules/eudr/encryption.js +33 -0
  183. package/dist/modules/eudr/encryption.js.map +7 -0
  184. package/dist/modules/eudr/events.js +38 -0
  185. package/dist/modules/eudr/events.js.map +7 -0
  186. package/dist/modules/eudr/index.js +15 -0
  187. package/dist/modules/eudr/index.js.map +7 -0
  188. package/dist/modules/eudr/lib/annual-report.js +104 -0
  189. package/dist/modules/eudr/lib/annual-report.js.map +7 -0
  190. package/dist/modules/eudr/lib/completeness.js +64 -0
  191. package/dist/modules/eudr/lib/completeness.js.map +7 -0
  192. package/dist/modules/eudr/lib/detail-read-scope.js +16 -0
  193. package/dist/modules/eudr/lib/detail-read-scope.js.map +7 -0
  194. package/dist/modules/eudr/lib/geometry.js +142 -0
  195. package/dist/modules/eudr/lib/geometry.js.map +7 -0
  196. package/dist/modules/eudr/lib/notifications.js +56 -0
  197. package/dist/modules/eudr/lib/notifications.js.map +7 -0
  198. package/dist/modules/eudr/lib/plural.js +26 -0
  199. package/dist/modules/eudr/lib/plural.js.map +7 -0
  200. package/dist/modules/eudr/lib/reference-data.js +240 -0
  201. package/dist/modules/eudr/lib/reference-data.js.map +7 -0
  202. package/dist/modules/eudr/lib/species.js +10 -0
  203. package/dist/modules/eudr/lib/species.js.map +7 -0
  204. package/dist/modules/eudr/lib/statement-lifecycle.js +84 -0
  205. package/dist/modules/eudr/lib/statement-lifecycle.js.map +7 -0
  206. package/dist/modules/eudr/lib/statement-seeding.js +49 -0
  207. package/dist/modules/eudr/lib/statement-seeding.js.map +7 -0
  208. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js +15 -0
  209. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js.map +7 -0
  210. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js +24 -0
  211. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js.map +7 -0
  212. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js +15 -0
  213. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js.map +7 -0
  214. package/dist/modules/eudr/notifications.js +58 -0
  215. package/dist/modules/eudr/notifications.js.map +7 -0
  216. package/dist/modules/eudr/search.js +186 -0
  217. package/dist/modules/eudr/search.js.map +7 -0
  218. package/dist/modules/eudr/setup.js +12 -0
  219. package/dist/modules/eudr/setup.js.map +7 -0
  220. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js +34 -0
  221. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js.map +7 -0
  222. package/dist/modules/eudr/subscribers/notify-risk-concluded.js +35 -0
  223. package/dist/modules/eudr/subscribers/notify-risk-concluded.js.map +7 -0
  224. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js +37 -0
  225. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js.map +7 -0
  226. package/dist/modules/eudr/subscribers/notify-statement-submitted.js +34 -0
  227. package/dist/modules/eudr/subscribers/notify-statement-submitted.js.map +7 -0
  228. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js +34 -0
  229. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js.map +7 -0
  230. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js +124 -0
  231. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js.map +7 -0
  232. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js +22 -0
  233. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js.map +7 -0
  234. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js +203 -0
  235. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js.map +7 -0
  236. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js +23 -0
  237. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js.map +7 -0
  238. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js +19 -0
  239. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js.map +7 -0
  240. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js +31 -0
  241. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js.map +7 -0
  242. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js +100 -0
  243. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js.map +7 -0
  244. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js +17 -0
  245. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js.map +7 -0
  246. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js +116 -0
  247. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js.map +7 -0
  248. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js +17 -0
  249. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js.map +7 -0
  250. package/dist/modules/eudr/widgets/injection-table.js +32 -0
  251. package/dist/modules/eudr/widgets/injection-table.js.map +7 -0
  252. package/dist/modules/notifications/lib/notificationService.js +67 -3
  253. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  254. package/dist/modules/query_index/lib/engine.js +121 -48
  255. package/dist/modules/query_index/lib/engine.js.map +2 -2
  256. package/dist/modules/sales/api/documents/factory.js +17 -0
  257. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  258. package/dist/modules/sales/commands/documents.js +32 -18
  259. package/dist/modules/sales/commands/documents.js.map +2 -2
  260. package/dist/modules/sales/data/entities.js +1 -0
  261. package/dist/modules/sales/data/entities.js.map +2 -2
  262. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js +17 -0
  263. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js.map +7 -0
  264. package/generated/entities/eudr_due_diligence_statement/index.ts +22 -0
  265. package/generated/entities/eudr_evidence_submission/index.ts +24 -0
  266. package/generated/entities/eudr_mitigation_action/index.ts +14 -0
  267. package/generated/entities/eudr_plot/index.ts +18 -0
  268. package/generated/entities/eudr_product_mapping/index.ts +14 -0
  269. package/generated/entities/eudr_risk_assessment/index.ts +16 -0
  270. package/generated/entities.ids.generated.ts +9 -0
  271. package/generated/entity-fields-registry.ts +120 -0
  272. package/package.json +7 -7
  273. package/src/modules/attachments/fields/attachment.tsx +5 -0
  274. package/src/modules/attachments/lib/crud.ts +2 -0
  275. package/src/modules/eudr/acl.ts +39 -0
  276. package/src/modules/eudr/ai-agents.ts +258 -0
  277. package/src/modules/eudr/ai-tools/compliance-pack.ts +618 -0
  278. package/src/modules/eudr/ai-tools/types.ts +44 -0
  279. package/src/modules/eudr/ai-tools.ts +15 -0
  280. package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +481 -0
  281. package/src/modules/eudr/api/evidence-submissions/route.ts +335 -0
  282. package/src/modules/eudr/api/mitigation-actions/route.ts +263 -0
  283. package/src/modules/eudr/api/openapi.ts +28 -0
  284. package/src/modules/eudr/api/plots/import/route.ts +369 -0
  285. package/src/modules/eudr/api/plots/route.ts +296 -0
  286. package/src/modules/eudr/api/product-mappings/route.ts +269 -0
  287. package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +382 -0
  288. package/src/modules/eudr/api/product-mappings/suggestions/route.ts +169 -0
  289. package/src/modules/eudr/api/reports/annual/route.ts +457 -0
  290. package/src/modules/eudr/api/risk-assessments/route.ts +323 -0
  291. package/src/modules/eudr/api/statements/[id]/export/route.ts +713 -0
  292. package/src/modules/eudr/api/statements/[id]/readiness/route.ts +129 -0
  293. package/src/modules/eudr/api/statements/route.ts +329 -0
  294. package/src/modules/eudr/api/suppliers/compliance/route.ts +241 -0
  295. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.ts +12 -0
  296. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.tsx +545 -0
  297. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.ts +13 -0
  298. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.tsx +383 -0
  299. package/src/modules/eudr/backend/eudr/evidence-submissions/page.meta.ts +12 -0
  300. package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +379 -0
  301. package/src/modules/eudr/backend/eudr/page.meta.ts +12 -0
  302. package/src/modules/eudr/backend/eudr/page.tsx +477 -0
  303. package/src/modules/eudr/backend/eudr/plots/[id]/page.meta.ts +12 -0
  304. package/src/modules/eudr/backend/eudr/plots/[id]/page.tsx +404 -0
  305. package/src/modules/eudr/backend/eudr/plots/create/page.meta.ts +13 -0
  306. package/src/modules/eudr/backend/eudr/plots/create/page.tsx +267 -0
  307. package/src/modules/eudr/backend/eudr/plots/page.meta.ts +12 -0
  308. package/src/modules/eudr/backend/eudr/plots/page.tsx +442 -0
  309. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.ts +12 -0
  310. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.tsx +311 -0
  311. package/src/modules/eudr/backend/eudr/product-mappings/create/page.meta.ts +13 -0
  312. package/src/modules/eudr/backend/eudr/product-mappings/create/page.tsx +190 -0
  313. package/src/modules/eudr/backend/eudr/product-mappings/page.meta.ts +12 -0
  314. package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +344 -0
  315. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.ts +12 -0
  316. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.tsx +421 -0
  317. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.meta.ts +13 -0
  318. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.tsx +247 -0
  319. package/src/modules/eudr/backend/eudr/risk-assessments/page.meta.ts +12 -0
  320. package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +383 -0
  321. package/src/modules/eudr/backend/eudr/statements/[id]/page.meta.ts +12 -0
  322. package/src/modules/eudr/backend/eudr/statements/[id]/page.tsx +777 -0
  323. package/src/modules/eudr/backend/eudr/statements/create/page.meta.ts +13 -0
  324. package/src/modules/eudr/backend/eudr/statements/create/page.tsx +511 -0
  325. package/src/modules/eudr/backend/eudr/statements/page.meta.ts +12 -0
  326. package/src/modules/eudr/backend/eudr/statements/page.tsx +372 -0
  327. package/src/modules/eudr/ce.ts +52 -0
  328. package/src/modules/eudr/commands/evidence-submissions.ts +699 -0
  329. package/src/modules/eudr/commands/index.ts +6 -0
  330. package/src/modules/eudr/commands/lifecycle-events.ts +28 -0
  331. package/src/modules/eudr/commands/mitigation-actions.ts +574 -0
  332. package/src/modules/eudr/commands/plots.ts +627 -0
  333. package/src/modules/eudr/commands/product-mappings.ts +556 -0
  334. package/src/modules/eudr/commands/risk-assessments.ts +728 -0
  335. package/src/modules/eudr/commands/statements.ts +933 -0
  336. package/src/modules/eudr/components/CountrySelectField.tsx +77 -0
  337. package/src/modules/eudr/components/GeometryInput.tsx +170 -0
  338. package/src/modules/eudr/components/MappingSuggestionsDialog.tsx +385 -0
  339. package/src/modules/eudr/components/MitigationActionsSection.tsx +417 -0
  340. package/src/modules/eudr/components/OrderSelectField.tsx +116 -0
  341. package/src/modules/eudr/components/PlotImportDialog.tsx +277 -0
  342. package/src/modules/eudr/components/PlotMapPreview.tsx +46 -0
  343. package/src/modules/eudr/components/PlotMapPreviewImpl.tsx +111 -0
  344. package/src/modules/eudr/components/PlotMultiSelectField.tsx +238 -0
  345. package/src/modules/eudr/components/RiskCriteriaField.tsx +173 -0
  346. package/src/modules/eudr/components/StatementLifecycleBar.tsx +363 -0
  347. package/src/modules/eudr/components/StatementReadinessChecklist.tsx +82 -0
  348. package/src/modules/eudr/components/StatementRiskSection.tsx +242 -0
  349. package/src/modules/eudr/components/crudErrorI18n.ts +36 -0
  350. package/src/modules/eudr/components/formConfig.tsx +717 -0
  351. package/src/modules/eudr/components/plotForm.ts +75 -0
  352. package/src/modules/eudr/data/enrichers.ts +82 -0
  353. package/src/modules/eudr/data/entities.ts +369 -0
  354. package/src/modules/eudr/data/validators.ts +357 -0
  355. package/src/modules/eudr/encryption.ts +31 -0
  356. package/src/modules/eudr/events.ts +38 -0
  357. package/src/modules/eudr/i18n/de.json +747 -0
  358. package/src/modules/eudr/i18n/en.json +747 -0
  359. package/src/modules/eudr/i18n/es.json +747 -0
  360. package/src/modules/eudr/i18n/ko.json +747 -0
  361. package/src/modules/eudr/i18n/pl.json +747 -0
  362. package/src/modules/eudr/index.ts +13 -0
  363. package/src/modules/eudr/lib/annual-report.ts +120 -0
  364. package/src/modules/eudr/lib/completeness.ts +90 -0
  365. package/src/modules/eudr/lib/detail-read-scope.ts +44 -0
  366. package/src/modules/eudr/lib/geometry.ts +191 -0
  367. package/src/modules/eudr/lib/notifications.ts +85 -0
  368. package/src/modules/eudr/lib/plural.ts +36 -0
  369. package/src/modules/eudr/lib/reference-data.ts +128 -0
  370. package/src/modules/eudr/lib/species.ts +12 -0
  371. package/src/modules/eudr/lib/statement-lifecycle.ts +109 -0
  372. package/src/modules/eudr/lib/statement-seeding.ts +86 -0
  373. package/src/modules/eudr/migrations/.snapshot-open-mercato.json +2046 -0
  374. package/src/modules/eudr/migrations/Migration20260706102002_eudr.ts +16 -0
  375. package/src/modules/eudr/migrations/Migration20260706152612_eudr.ts +30 -0
  376. package/src/modules/eudr/migrations/Migration20260722100000_eudr.ts +17 -0
  377. package/src/modules/eudr/notifications.ts +56 -0
  378. package/src/modules/eudr/search.ts +212 -0
  379. package/src/modules/eudr/setup.ts +10 -0
  380. package/src/modules/eudr/subscribers/notify-mitigation-completed.ts +56 -0
  381. package/src/modules/eudr/subscribers/notify-risk-concluded.ts +58 -0
  382. package/src/modules/eudr/subscribers/notify-statement-reference-issued.ts +59 -0
  383. package/src/modules/eudr/subscribers/notify-statement-submitted.ts +49 -0
  384. package/src/modules/eudr/subscribers/notify-statement-withdrawn.ts +49 -0
  385. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-created.ts +189 -0
  386. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.ts +31 -0
  387. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.client.tsx +271 -0
  388. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.ts +24 -0
  389. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.client.tsx +37 -0
  390. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.ts +30 -0
  391. package/src/modules/eudr/widgets/injection/order-compliance/widget.client.tsx +131 -0
  392. package/src/modules/eudr/widgets/injection/order-compliance/widget.ts +16 -0
  393. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.client.tsx +168 -0
  394. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.ts +16 -0
  395. package/src/modules/eudr/widgets/injection-table.ts +31 -0
  396. package/src/modules/notifications/lib/notificationService.ts +83 -4
  397. package/src/modules/query_index/lib/engine.ts +139 -51
  398. package/src/modules/sales/api/documents/factory.ts +29 -0
  399. package/src/modules/sales/commands/documents.ts +65 -18
  400. package/src/modules/sales/data/entities.ts +1 -0
  401. package/src/modules/sales/migrations/.snapshot-open-mercato.json +10 -0
  402. package/src/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.ts +59 -0
@@ -0,0 +1,495 @@
1
+ import { z } from "zod";
2
+ import { createLogger } from "@open-mercato/shared/lib/logger";
3
+ import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
4
+ import { E } from "../../../generated/entities.ids.generated.js";
5
+ import {
6
+ EudrDueDiligenceStatement,
7
+ EudrEvidenceSubmission,
8
+ EudrMitigationAction,
9
+ EudrProductMapping,
10
+ EudrRiskAssessment
11
+ } from "../data/entities.js";
12
+ import {
13
+ EUDR_COMMODITIES,
14
+ EUDR_STATEMENT_STATUSES,
15
+ EUDR_SUBMISSION_STATUSES
16
+ } from "../data/validators.js";
17
+ import {
18
+ EUDR_APPLICATION_DATES,
19
+ EUDR_HIGH_RISK_COUNTRIES,
20
+ EUDR_LOW_RISK_COUNTRIES,
21
+ getCountryRiskTier,
22
+ suggestCommodityForHsCode
23
+ } from "../lib/reference-data.js";
24
+ import {
25
+ evaluateSubmissionGate
26
+ } from "../lib/statement-lifecycle.js";
27
+ import { assertTenantScope } from "./types.js";
28
+ const logger = createLogger("eudr").child({ component: "ai-tools/compliance-pack" });
29
+ const DAY_MS = 24 * 60 * 60 * 1e3;
30
+ const overviewInput = z.object({}).strict();
31
+ const listStatementReadinessInput = z.object({
32
+ statementId: z.string().uuid().optional(),
33
+ limit: z.coerce.number().int().min(1).max(50).default(10)
34
+ }).strict();
35
+ const listEvidenceGapsInput = z.object({
36
+ commodity: z.enum(EUDR_COMMODITIES).optional(),
37
+ supplierEntityId: z.string().uuid().optional(),
38
+ limit: z.coerce.number().int().min(1).max(100).default(25)
39
+ }).strict();
40
+ const checkProductScopeInput = z.object({
41
+ productId: z.string().uuid().optional(),
42
+ hsCode: z.string().trim().min(1).max(20).optional()
43
+ }).strict().refine((input) => input.productId !== void 0 || input.hsCode !== void 0, {
44
+ message: "Provide productId or hsCode"
45
+ });
46
+ const getCountryRiskInput = z.object({
47
+ country: z.string().trim().regex(/^[A-Za-z]{2}$/).transform((value) => value.toUpperCase()).optional(),
48
+ includeLowList: z.boolean().optional()
49
+ }).strict();
50
+ function resolveEm(ctx) {
51
+ return ctx.container.resolve("em");
52
+ }
53
+ function forked(em) {
54
+ return em.fork();
55
+ }
56
+ function toIsoString(value) {
57
+ if (value == null) return null;
58
+ if (value instanceof Date) return value.toISOString();
59
+ if (value.length === 0) return null;
60
+ const date = new Date(value);
61
+ return Number.isNaN(date.getTime()) ? value : date.toISOString();
62
+ }
63
+ function asNumber(value) {
64
+ if (typeof value === "number" && Number.isFinite(value)) return value;
65
+ if (typeof value === "string" && value.trim().length > 0) {
66
+ const parsed = Number(value);
67
+ if (Number.isFinite(parsed)) return parsed;
68
+ }
69
+ return 0;
70
+ }
71
+ function stringArray(value) {
72
+ if (!Array.isArray(value)) return [];
73
+ return value.filter((entry) => typeof entry === "string");
74
+ }
75
+ function readString(value) {
76
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
77
+ }
78
+ function daysLeft(deadline, now) {
79
+ const deadlineDate = /* @__PURE__ */ new Date(`${deadline}T00:00:00.000Z`);
80
+ return Math.ceil((deadlineDate.getTime() - now.getTime()) / DAY_MS);
81
+ }
82
+ function countRowsByStatus(em, entity, statuses, scope) {
83
+ return Promise.all(
84
+ statuses.map(async (status) => {
85
+ const count = await forked(em).count(entity, {
86
+ tenantId: scope.tenantId,
87
+ organizationId: scope.organizationId,
88
+ deletedAt: null,
89
+ status
90
+ });
91
+ return [status, count];
92
+ })
93
+ ).then((entries) => Object.fromEntries(entries));
94
+ }
95
+ async function fetchAverageCompleteness(em, scope) {
96
+ const rows = await em.getConnection().execute(
97
+ `select avg(completeness_score) as avg_completeness
98
+ from eudr_evidence_submissions
99
+ where tenant_id = ?
100
+ and organization_id = ?
101
+ and deleted_at is null`,
102
+ [scope.tenantId, scope.organizationId]
103
+ );
104
+ const value = rows[0]?.avg_completeness ?? null;
105
+ if (value === null) return null;
106
+ const parsed = typeof value === "number" ? value : Number(value);
107
+ return Number.isFinite(parsed) ? parsed : null;
108
+ }
109
+ function hasConcernAnswers(criteria) {
110
+ return Object.values(criteria).some((entry) => entry.answer === "concern");
111
+ }
112
+ function buildReadinessGaps(submissions) {
113
+ return submissions.filter((submission) => submission.status !== "verified" || asNumber(submission.completenessScore) !== 100).map((submission) => ({
114
+ submissionId: submission.id,
115
+ status: submission.status,
116
+ completenessScore: asNumber(submission.completenessScore),
117
+ missingFields: stringArray(submission.missingFields)
118
+ }));
119
+ }
120
+ function riskSummary(assessment) {
121
+ if (!assessment) return null;
122
+ return {
123
+ conclusion: assessment.conclusion,
124
+ overallTier: assessment.overallTier,
125
+ reviewDueAt: toIsoString(assessment.reviewDueAt)
126
+ };
127
+ }
128
+ async function loadSubmissionsForStatements(em, statementIds, scope) {
129
+ const byStatement = /* @__PURE__ */ new Map();
130
+ if (!statementIds.length) return byStatement;
131
+ const submissions = await findWithDecryption(
132
+ em,
133
+ EudrEvidenceSubmission,
134
+ {
135
+ statementId: { $in: statementIds },
136
+ tenantId: scope.tenantId,
137
+ organizationId: scope.organizationId,
138
+ deletedAt: null
139
+ },
140
+ { orderBy: { createdAt: "ASC" } },
141
+ scope
142
+ );
143
+ for (const submission of submissions) {
144
+ if (!submission.statementId) continue;
145
+ const existing = byStatement.get(submission.statementId) ?? [];
146
+ existing.push(submission);
147
+ byStatement.set(submission.statementId, existing);
148
+ }
149
+ return byStatement;
150
+ }
151
+ async function loadLatestAssessmentsForStatements(em, statementIds, scope) {
152
+ const latestByStatement = /* @__PURE__ */ new Map();
153
+ if (!statementIds.length) return latestByStatement;
154
+ const assessments = await findWithDecryption(
155
+ em,
156
+ EudrRiskAssessment,
157
+ {
158
+ statementId: { $in: statementIds },
159
+ tenantId: scope.tenantId,
160
+ organizationId: scope.organizationId,
161
+ deletedAt: null
162
+ },
163
+ { orderBy: { assessedAt: "DESC", createdAt: "DESC" } },
164
+ scope
165
+ );
166
+ for (const assessment of assessments) {
167
+ if (latestByStatement.has(assessment.statementId)) continue;
168
+ latestByStatement.set(assessment.statementId, assessment);
169
+ }
170
+ return latestByStatement;
171
+ }
172
+ async function buildGateAssessment(em, assessment, scope) {
173
+ if (!assessment) return null;
174
+ const completedMitigationCount = await em.count(EudrMitigationAction, {
175
+ riskAssessmentId: assessment.id,
176
+ tenantId: scope.tenantId,
177
+ organizationId: scope.organizationId,
178
+ status: "completed",
179
+ deletedAt: null
180
+ });
181
+ return {
182
+ conclusion: assessment.conclusion,
183
+ countryRisks: assessment.countryRisks.map((risk) => ({ country: risk.country, tier: risk.tier })),
184
+ reviewDueAt: assessment.reviewDueAt ?? null,
185
+ hasConcernAnswers: hasConcernAnswers(assessment.criteria),
186
+ hasCompletedMitigation: completedMitigationCount > 0
187
+ };
188
+ }
189
+ const GATE_REASON_TEXT = {
190
+ referencedStatementsRequired: "Referenced due diligence statement numbers are required for SME trader statements.",
191
+ noSubmissions: "No evidence submissions are linked to this statement.",
192
+ submissionsNotReady: "All linked evidence submissions must be verified and 100% complete.",
193
+ originCountryMissing: "Every linked evidence submission must include an origin country.",
194
+ riskConclusionMissing: "A latest negligible-risk assessment is required unless all origin countries are low risk.",
195
+ riskAssessmentStale: "The latest risk assessment does not cover the current set of origin countries.",
196
+ riskReviewOverdue: "The latest risk assessment review date is overdue.",
197
+ mitigationIncomplete: "At least one completed mitigation action is required for concern answers."
198
+ };
199
+ function gateReasonKey(reason) {
200
+ return `eudr.gate.${reason}`;
201
+ }
202
+ function gateReasonText(reason) {
203
+ return GATE_REASON_TEXT[reason] ?? reason;
204
+ }
205
+ async function loadCatalogProductById(ctx, productId) {
206
+ if (!productId) return null;
207
+ try {
208
+ const queryEngine = ctx.container.resolve("queryEngine");
209
+ const scope = assertTenantScope(ctx);
210
+ const result = await queryEngine.query(E.catalog.catalog_product, {
211
+ fields: ["id", "title", "name", "sku", "hs_code"],
212
+ filters: [
213
+ { field: "id", op: "eq", value: productId }
214
+ ],
215
+ page: { page: 1, pageSize: 1 },
216
+ tenantId: scope.tenantId,
217
+ organizationId: scope.organizationId
218
+ });
219
+ const product = result.items[0];
220
+ if (!product) return null;
221
+ const id = readString(product.id);
222
+ if (!id) return null;
223
+ return {
224
+ id,
225
+ name: readString(product.title) ?? readString(product.name),
226
+ sku: readString(product.sku),
227
+ hsCode: readString(product.hs_code)
228
+ };
229
+ } catch (err) {
230
+ logger.warn("catalog product lookup failed", { err });
231
+ throw err;
232
+ }
233
+ }
234
+ const getComplianceOverviewTool = {
235
+ name: "eudr.get_compliance_overview",
236
+ displayName: "Get EUDR compliance overview",
237
+ description: "Returns a live EUDR readiness dashboard for the current tenant and organization. Use this when the operator asks for overall compliance status, deadlines, how many mappings/submissions/statements exist, or whether risk reviews are coming due. Fields returned: deadline { date, daysLeft }, mappingsInScope, submissions { total, byStatus, incomplete, avgCompleteness }, statements { total, byStatus, notReady, missingReference }, and riskReviewsDueSoon.",
238
+ inputSchema: overviewInput,
239
+ requiredFeatures: ["eudr.statements.view", "eudr.mappings.view", "eudr.submissions.view", "eudr.risk.view"],
240
+ tags: ["read", "eudr", "overview", "compliance"],
241
+ isMutation: false,
242
+ handler: async (rawInput, ctx) => {
243
+ overviewInput.parse(rawInput);
244
+ const scope = assertTenantScope(ctx);
245
+ const em = resolveEm(ctx);
246
+ const now = /* @__PURE__ */ new Date();
247
+ const reviewWindowEnd = new Date(now.getTime() + 30 * DAY_MS);
248
+ const [
249
+ mappingsInScope,
250
+ submissionsTotal,
251
+ submissionsByStatus,
252
+ avgCompleteness,
253
+ incomplete,
254
+ statementsTotal,
255
+ statementsByStatus,
256
+ notReady,
257
+ missingReference,
258
+ riskReviewsDueSoon
259
+ ] = await Promise.all([
260
+ forked(em).count(EudrProductMapping, { ...scope, deletedAt: null, isInScope: true }),
261
+ forked(em).count(EudrEvidenceSubmission, { ...scope, deletedAt: null }),
262
+ countRowsByStatus(em, EudrEvidenceSubmission, EUDR_SUBMISSION_STATUSES, scope),
263
+ fetchAverageCompleteness(forked(em), scope),
264
+ forked(em).count(EudrEvidenceSubmission, {
265
+ ...scope,
266
+ deletedAt: null,
267
+ completenessScore: { $lt: 100 }
268
+ }),
269
+ forked(em).count(EudrDueDiligenceStatement, { ...scope, deletedAt: null }),
270
+ countRowsByStatus(em, EudrDueDiligenceStatement, EUDR_STATEMENT_STATUSES, scope),
271
+ forked(em).count(EudrDueDiligenceStatement, { ...scope, deletedAt: null, status: "draft" }),
272
+ forked(em).count(EudrDueDiligenceStatement, {
273
+ ...scope,
274
+ deletedAt: null,
275
+ status: { $in: ["submitted", "available"] },
276
+ referenceNumber: null
277
+ }),
278
+ forked(em).count(EudrRiskAssessment, {
279
+ ...scope,
280
+ deletedAt: null,
281
+ reviewDueAt: { $gte: now, $lte: reviewWindowEnd }
282
+ })
283
+ ]);
284
+ return {
285
+ deadline: {
286
+ date: EUDR_APPLICATION_DATES.largeAndMedium,
287
+ daysLeft: daysLeft(EUDR_APPLICATION_DATES.largeAndMedium, now)
288
+ },
289
+ mappingsInScope,
290
+ submissions: {
291
+ total: submissionsTotal,
292
+ byStatus: submissionsByStatus,
293
+ avgCompleteness,
294
+ incomplete
295
+ },
296
+ statements: {
297
+ total: statementsTotal,
298
+ byStatus: statementsByStatus,
299
+ notReady,
300
+ missingReference
301
+ },
302
+ riskReviewsDueSoon
303
+ };
304
+ }
305
+ };
306
+ const listStatementReadinessTool = {
307
+ name: "eudr.list_statement_readiness",
308
+ displayName: "List EUDR statement readiness",
309
+ description: "Checks due diligence statement export/submission readiness for one statement or the most recent non-archived statements. Use this when the operator asks whether statements are ready to submit/export, why a draft cannot move forward, what evidence is blocking a statement, or what the latest risk result says. Fields returned per item: id, title, status, commodity, readiness { ready, submissionCount, verifiedCount, completeCount, gaps [{ submissionId, status, completenessScore, missingFields }] }, latestRisk { conclusion, overallTier, reviewDueAt } or null, gateReasons as eudr.gate.* keys, and gateReasonsPlainText.",
310
+ inputSchema: listStatementReadinessInput,
311
+ requiredFeatures: ["eudr.statements.view", "eudr.submissions.view", "eudr.risk.view"],
312
+ tags: ["read", "eudr", "statements", "readiness"],
313
+ isMutation: false,
314
+ handler: async (rawInput, ctx) => {
315
+ const input = listStatementReadinessInput.parse(rawInput);
316
+ const scope = assertTenantScope(ctx);
317
+ const em = resolveEm(ctx);
318
+ const statementWhere = input.statementId ? {
319
+ id: input.statementId,
320
+ tenantId: scope.tenantId,
321
+ organizationId: scope.organizationId,
322
+ deletedAt: null
323
+ } : {
324
+ tenantId: scope.tenantId,
325
+ organizationId: scope.organizationId,
326
+ deletedAt: null,
327
+ status: { $ne: "archived" }
328
+ };
329
+ const statements = await em.find(EudrDueDiligenceStatement, statementWhere, {
330
+ orderBy: { updatedAt: "DESC", createdAt: "DESC" },
331
+ limit: input.statementId ? 1 : input.limit
332
+ });
333
+ const statementIds = statements.map((statement) => statement.id);
334
+ const submissionsByStatement = await loadSubmissionsForStatements(em, statementIds, scope);
335
+ const latestRiskByStatement = await loadLatestAssessmentsForStatements(em, statementIds, scope);
336
+ const items = await Promise.all(
337
+ statements.map(async (statement) => {
338
+ const submissions = submissionsByStatement.get(statement.id) ?? [];
339
+ const latestAssessment = latestRiskByStatement.get(statement.id) ?? null;
340
+ const readinessGaps = buildReadinessGaps(submissions);
341
+ const gateSubmissions = submissions.map((submission) => ({
342
+ status: submission.status,
343
+ completenessScore: asNumber(submission.completenessScore),
344
+ originCountry: submission.originCountry ?? null
345
+ }));
346
+ const gate = evaluateSubmissionGate({
347
+ actorRole: statement.actorRole ?? null,
348
+ referencedStatementsCount: Array.isArray(statement.referencedStatements) ? statement.referencedStatements.length : 0,
349
+ submissions: gateSubmissions,
350
+ latestAssessment: await buildGateAssessment(forked(em), latestAssessment, scope)
351
+ });
352
+ return {
353
+ id: statement.id,
354
+ title: statement.title,
355
+ status: statement.status,
356
+ commodity: statement.commodity,
357
+ readiness: {
358
+ ready: submissions.length > 0 && readinessGaps.length === 0,
359
+ submissionCount: submissions.length,
360
+ verifiedCount: submissions.filter((submission) => submission.status === "verified").length,
361
+ completeCount: submissions.filter((submission) => asNumber(submission.completenessScore) === 100).length,
362
+ gaps: readinessGaps
363
+ },
364
+ latestRisk: riskSummary(latestAssessment),
365
+ gateReasons: gate.reasons.map(gateReasonKey),
366
+ gateReasonsPlainText: gate.reasons.map(gateReasonText)
367
+ };
368
+ })
369
+ );
370
+ return {
371
+ items,
372
+ count: items.length
373
+ };
374
+ }
375
+ };
376
+ const listEvidenceGapsTool = {
377
+ name: "eudr.list_evidence_gaps",
378
+ displayName: "List EUDR evidence gaps",
379
+ description: "Lists incomplete EUDR evidence submissions for the current tenant and organization. Use this when the operator asks what supplier evidence is missing, which submissions are incomplete, which origin countries increase risk, or where to focus cleanup. Fields returned per item: id, supplier, commodity, status, completenessScore, missingFields, originCountry, and countryRiskTier.",
380
+ inputSchema: listEvidenceGapsInput,
381
+ requiredFeatures: ["eudr.submissions.view"],
382
+ tags: ["read", "eudr", "submissions", "gaps"],
383
+ isMutation: false,
384
+ handler: async (rawInput, ctx) => {
385
+ const input = listEvidenceGapsInput.parse(rawInput);
386
+ const scope = assertTenantScope(ctx);
387
+ const em = resolveEm(ctx);
388
+ const where = {
389
+ tenantId: scope.tenantId,
390
+ organizationId: scope.organizationId,
391
+ deletedAt: null,
392
+ completenessScore: { $lt: 100 }
393
+ };
394
+ if (input.commodity) where.commodity = input.commodity;
395
+ if (input.supplierEntityId) where.supplierEntityId = input.supplierEntityId;
396
+ const submissions = await findWithDecryption(
397
+ em,
398
+ EudrEvidenceSubmission,
399
+ where,
400
+ { orderBy: { completenessScore: "ASC", updatedAt: "DESC" }, limit: input.limit },
401
+ scope
402
+ );
403
+ return {
404
+ items: submissions.map((submission) => ({
405
+ id: submission.id,
406
+ supplier: submission.supplierSnapshot?.displayName ?? null,
407
+ commodity: submission.commodity,
408
+ status: submission.status,
409
+ completenessScore: asNumber(submission.completenessScore),
410
+ missingFields: stringArray(submission.missingFields),
411
+ originCountry: submission.originCountry ?? null,
412
+ countryRiskTier: getCountryRiskTier(submission.originCountry ?? null)
413
+ })),
414
+ count: submissions.length,
415
+ limit: input.limit
416
+ };
417
+ }
418
+ };
419
+ const checkProductScopeTool = {
420
+ name: "eudr.check_product_scope",
421
+ displayName: "Check EUDR product scope",
422
+ description: "Checks whether a product or HS code appears in EUDR Annex I scope. Use this when the operator asks if a product needs EUDR mapping, wants a commodity suggestion from an HS code, or needs to compare existing mappings against catalog HS data. Fields returned: existingMappings [{ id, commodity, isInScope, hsCode }], catalogProduct { id, name, sku, hsCode } or null, suggestedCommodity, and inAnnexScope.",
423
+ inputSchema: checkProductScopeInput,
424
+ requiredFeatures: ["eudr.mappings.view"],
425
+ tags: ["read", "eudr", "mappings", "scope"],
426
+ isMutation: false,
427
+ handler: async (rawInput, ctx) => {
428
+ const input = checkProductScopeInput.parse(rawInput);
429
+ const scope = assertTenantScope(ctx);
430
+ const em = resolveEm(ctx);
431
+ const catalogProduct = await loadCatalogProductById(ctx, input.productId);
432
+ const existingMappings = input.productId ? await em.find(EudrProductMapping, {
433
+ productId: input.productId,
434
+ tenantId: scope.tenantId,
435
+ organizationId: scope.organizationId,
436
+ deletedAt: null
437
+ }, {
438
+ orderBy: { createdAt: "DESC" },
439
+ limit: 50
440
+ }) : [];
441
+ const effectiveHsCode = input.hsCode ?? catalogProduct?.hsCode ?? null;
442
+ const suggestedCommodity = suggestCommodityForHsCode(effectiveHsCode);
443
+ return {
444
+ existingMappings: existingMappings.map((mapping) => ({
445
+ id: mapping.id,
446
+ commodity: mapping.commodity,
447
+ isInScope: mapping.isInScope,
448
+ hsCode: mapping.hsCode ?? null
449
+ })),
450
+ catalogProduct,
451
+ suggestedCommodity,
452
+ inAnnexScope: suggestedCommodity !== null
453
+ };
454
+ }
455
+ };
456
+ const getCountryRiskTool = {
457
+ name: "eudr.get_country_risk",
458
+ displayName: "Get EUDR country risk",
459
+ description: "Returns the current EUDR country-risk tier from the module reference data. Use this when the operator asks whether a specific origin country is low, standard, high, or unknown risk, or when they need the compact high-risk list. With country, returns { country, tier }. Without country, returns { high, lowCount, note } and only includes the low-risk list when includeLowList is true.",
460
+ inputSchema: getCountryRiskInput,
461
+ // Static, law-versioned reference data — no tenant rows are read, so this is
462
+ // gated on the module's lowest-privilege view feature rather than submissions.
463
+ requiredFeatures: ["eudr.mappings.view"],
464
+ tags: ["read", "eudr", "country-risk", "reference-data"],
465
+ isMutation: false,
466
+ handler: async (rawInput, ctx) => {
467
+ const input = getCountryRiskInput.parse(rawInput);
468
+ assertTenantScope(ctx);
469
+ if (input.country) {
470
+ return {
471
+ country: input.country,
472
+ tier: getCountryRiskTier(input.country)
473
+ };
474
+ }
475
+ return {
476
+ high: [...EUDR_HIGH_RISK_COUNTRIES],
477
+ lowCount: EUDR_LOW_RISK_COUNTRIES.length,
478
+ ...input.includeLowList === true ? { low: [...EUDR_LOW_RISK_COUNTRIES] } : {},
479
+ note: "Unlisted countries are standard risk."
480
+ };
481
+ }
482
+ };
483
+ const eudrComplianceAiTools = [
484
+ getComplianceOverviewTool,
485
+ listStatementReadinessTool,
486
+ listEvidenceGapsTool,
487
+ checkProductScopeTool,
488
+ getCountryRiskTool
489
+ ];
490
+ var compliance_pack_default = eudrComplianceAiTools;
491
+ export {
492
+ compliance_pack_default as default,
493
+ eudrComplianceAiTools
494
+ };
495
+ //# sourceMappingURL=compliance-pack.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/ai-tools/compliance-pack.ts"],
4
+ "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { z } from 'zod'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n EudrDueDiligenceStatement,\n EudrEvidenceSubmission,\n EudrMitigationAction,\n EudrProductMapping,\n EudrRiskAssessment,\n} from '../data/entities'\nimport {\n EUDR_COMMODITIES,\n EUDR_STATEMENT_STATUSES,\n EUDR_SUBMISSION_STATUSES,\n} from '../data/validators'\nimport {\n EUDR_APPLICATION_DATES,\n EUDR_HIGH_RISK_COUNTRIES,\n EUDR_LOW_RISK_COUNTRIES,\n getCountryRiskTier,\n suggestCommodityForHsCode,\n} from '../lib/reference-data'\nimport {\n evaluateSubmissionGate,\n type GateAssessmentView,\n type GateSubmissionView,\n} from '../lib/statement-lifecycle'\nimport { assertTenantScope, type EudrAiToolDefinition, type EudrToolContext } from './types'\n\ntype Scope = {\n tenantId: string\n organizationId: string\n}\n\ntype AvgCompletenessRow = {\n avg_completeness: string | number | null\n}\n\ntype CatalogProductRecord = Record<string, unknown> & {\n id?: unknown\n title?: unknown\n name?: unknown\n sku?: unknown\n hs_code?: unknown\n}\n\ntype ReadinessGap = {\n submissionId: string\n status: string\n completenessScore: number\n missingFields: string[]\n}\n\nconst logger = createLogger('eudr').child({ component: 'ai-tools/compliance-pack' })\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nconst overviewInput = z.object({}).strict()\n\nconst listStatementReadinessInput = z\n .object({\n statementId: z.string().uuid().optional(),\n limit: z.coerce.number().int().min(1).max(50).default(10),\n })\n .strict()\n\nconst listEvidenceGapsInput = z\n .object({\n commodity: z.enum(EUDR_COMMODITIES).optional(),\n supplierEntityId: z.string().uuid().optional(),\n limit: z.coerce.number().int().min(1).max(100).default(25),\n })\n .strict()\n\nconst checkProductScopeInput = z\n .object({\n productId: z.string().uuid().optional(),\n hsCode: z.string().trim().min(1).max(20).optional(),\n })\n .strict()\n .refine((input) => input.productId !== undefined || input.hsCode !== undefined, {\n message: 'Provide productId or hsCode',\n })\n\nconst getCountryRiskInput = z\n .object({\n country: z\n .string()\n .trim()\n .regex(/^[A-Za-z]{2}$/)\n .transform((value) => value.toUpperCase())\n .optional(),\n includeLowList: z.boolean().optional(),\n })\n .strict()\n\nfunction resolveEm(ctx: EudrToolContext): EntityManager {\n return ctx.container.resolve<EntityManager>('em')\n}\n\n/**\n * A MikroORM EntityManager is not concurrency-safe: parallel work on one\n * instance shares its identity map and unit of work. Every branch that runs\n * inside a `Promise.all` here gets its own fork.\n */\nfunction forked(em: EntityManager): EntityManager {\n return em.fork()\n}\n\nfunction toIsoString(value: Date | string | null | undefined): string | null {\n if (value == null) return null\n if (value instanceof Date) return value.toISOString()\n if (value.length === 0) return null\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : date.toISOString()\n}\n\nfunction asNumber(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n }\n return 0\n}\n\nfunction stringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value.filter((entry): entry is string => typeof entry === 'string')\n}\n\nfunction readString(value: unknown): string | null {\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null\n}\n\nfunction daysLeft(deadline: string, now: Date): number {\n const deadlineDate = new Date(`${deadline}T00:00:00.000Z`)\n return Math.ceil((deadlineDate.getTime() - now.getTime()) / DAY_MS)\n}\n\nfunction countRowsByStatus<T extends object>(\n em: EntityManager,\n entity: new () => T,\n statuses: readonly string[],\n scope: Scope,\n): Promise<Record<string, number>> {\n return Promise.all(\n statuses.map(async (status) => {\n const count = await forked(em).count(entity, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n status,\n } as FilterQuery<T>)\n return [status, count] as const\n }),\n ).then((entries) => Object.fromEntries(entries))\n}\n\nasync function fetchAverageCompleteness(em: EntityManager, scope: Scope): Promise<number | null> {\n const rows = await em.getConnection().execute(\n `select avg(completeness_score) as avg_completeness\n from eudr_evidence_submissions\n where tenant_id = ?\n and organization_id = ?\n and deleted_at is null`,\n [scope.tenantId, scope.organizationId],\n ) as AvgCompletenessRow[]\n const value = rows[0]?.avg_completeness ?? null\n if (value === null) return null\n const parsed = typeof value === 'number' ? value : Number(value)\n return Number.isFinite(parsed) ? parsed : null\n}\n\nfunction hasConcernAnswers(criteria: Record<string, { answer?: string }>): boolean {\n return Object.values(criteria).some((entry) => entry.answer === 'concern')\n}\n\nfunction buildReadinessGaps(submissions: EudrEvidenceSubmission[]): ReadinessGap[] {\n return submissions\n .filter((submission) => submission.status !== 'verified' || asNumber(submission.completenessScore) !== 100)\n .map((submission) => ({\n submissionId: submission.id,\n status: submission.status,\n completenessScore: asNumber(submission.completenessScore),\n missingFields: stringArray(submission.missingFields),\n }))\n}\n\nfunction riskSummary(assessment: EudrRiskAssessment | null) {\n if (!assessment) return null\n return {\n conclusion: assessment.conclusion,\n overallTier: assessment.overallTier,\n reviewDueAt: toIsoString(assessment.reviewDueAt),\n }\n}\n\nasync function loadSubmissionsForStatements(\n em: EntityManager,\n statementIds: string[],\n scope: Scope,\n): Promise<Map<string, EudrEvidenceSubmission[]>> {\n const byStatement = new Map<string, EudrEvidenceSubmission[]>()\n if (!statementIds.length) return byStatement\n const submissions = await findWithDecryption(\n em,\n EudrEvidenceSubmission,\n {\n statementId: { $in: statementIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n } as FilterQuery<EudrEvidenceSubmission>,\n { orderBy: { createdAt: 'ASC' } },\n scope,\n )\n for (const submission of submissions) {\n if (!submission.statementId) continue\n const existing = byStatement.get(submission.statementId) ?? []\n existing.push(submission)\n byStatement.set(submission.statementId, existing)\n }\n return byStatement\n}\n\nasync function loadLatestAssessmentsForStatements(\n em: EntityManager,\n statementIds: string[],\n scope: Scope,\n): Promise<Map<string, EudrRiskAssessment>> {\n const latestByStatement = new Map<string, EudrRiskAssessment>()\n if (!statementIds.length) return latestByStatement\n const assessments = await findWithDecryption(\n em,\n EudrRiskAssessment,\n {\n statementId: { $in: statementIds },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n } as FilterQuery<EudrRiskAssessment>,\n { orderBy: { assessedAt: 'DESC', createdAt: 'DESC' } },\n scope,\n )\n for (const assessment of assessments) {\n if (latestByStatement.has(assessment.statementId)) continue\n latestByStatement.set(assessment.statementId, assessment)\n }\n return latestByStatement\n}\n\nasync function buildGateAssessment(\n em: EntityManager,\n assessment: EudrRiskAssessment | null,\n scope: Scope,\n): Promise<GateAssessmentView> {\n if (!assessment) return null\n const completedMitigationCount = await em.count(EudrMitigationAction, {\n riskAssessmentId: assessment.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n status: 'completed',\n deletedAt: null,\n })\n return {\n conclusion: assessment.conclusion,\n countryRisks: assessment.countryRisks.map((risk) => ({ country: risk.country, tier: risk.tier })),\n reviewDueAt: assessment.reviewDueAt ?? null,\n hasConcernAnswers: hasConcernAnswers(assessment.criteria),\n hasCompletedMitigation: completedMitigationCount > 0,\n }\n}\n\nconst GATE_REASON_TEXT: Record<string, string> = {\n referencedStatementsRequired: 'Referenced due diligence statement numbers are required for SME trader statements.',\n noSubmissions: 'No evidence submissions are linked to this statement.',\n submissionsNotReady: 'All linked evidence submissions must be verified and 100% complete.',\n originCountryMissing: 'Every linked evidence submission must include an origin country.',\n riskConclusionMissing: 'A latest negligible-risk assessment is required unless all origin countries are low risk.',\n riskAssessmentStale: 'The latest risk assessment does not cover the current set of origin countries.',\n riskReviewOverdue: 'The latest risk assessment review date is overdue.',\n mitigationIncomplete: 'At least one completed mitigation action is required for concern answers.',\n}\n\nfunction gateReasonKey(reason: string): string {\n return `eudr.gate.${reason}`\n}\n\nfunction gateReasonText(reason: string): string {\n return GATE_REASON_TEXT[reason] ?? reason\n}\n\nasync function loadCatalogProductById(\n ctx: EudrToolContext,\n productId: string | undefined,\n): Promise<{\n id: string\n name: string | null\n sku: string | null\n hsCode: string | null\n} | null> {\n if (!productId) return null\n try {\n const queryEngine = ctx.container.resolve<QueryEngine>('queryEngine')\n const scope = assertTenantScope(ctx)\n const result = await queryEngine.query<CatalogProductRecord>(E.catalog.catalog_product, {\n fields: ['id', 'title', 'name', 'sku', 'hs_code'],\n filters: [\n { field: 'id', op: 'eq', value: productId },\n ],\n page: { page: 1, pageSize: 1 },\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n const product = result.items[0]\n if (!product) return null\n const id = readString(product.id)\n if (!id) return null\n return {\n id,\n name: readString(product.title) ?? readString(product.name),\n sku: readString(product.sku),\n hsCode: readString(product.hs_code),\n }\n } catch (err) {\n // A lookup failure is not the same as \"product does not exist\"; surface it so\n // check_product_scope cannot report an absent product on an infra error.\n logger.warn('catalog product lookup failed', { err })\n throw err\n }\n}\n\nconst getComplianceOverviewTool: EudrAiToolDefinition = {\n name: 'eudr.get_compliance_overview',\n displayName: 'Get EUDR compliance overview',\n description:\n 'Returns a live EUDR readiness dashboard for the current tenant and organization. Use this when the operator asks for overall compliance status, deadlines, how many mappings/submissions/statements exist, or whether risk reviews are coming due. Fields returned: deadline { date, daysLeft }, mappingsInScope, submissions { total, byStatus, incomplete, avgCompleteness }, statements { total, byStatus, notReady, missingReference }, and riskReviewsDueSoon.',\n inputSchema: overviewInput,\n requiredFeatures: ['eudr.statements.view', 'eudr.mappings.view', 'eudr.submissions.view', 'eudr.risk.view'],\n tags: ['read', 'eudr', 'overview', 'compliance'],\n isMutation: false,\n handler: async (rawInput, ctx) => {\n overviewInput.parse(rawInput)\n const scope = assertTenantScope(ctx)\n const em = resolveEm(ctx)\n const now = new Date()\n const reviewWindowEnd = new Date(now.getTime() + 30 * DAY_MS)\n\n const [\n mappingsInScope,\n submissionsTotal,\n submissionsByStatus,\n avgCompleteness,\n incomplete,\n statementsTotal,\n statementsByStatus,\n notReady,\n missingReference,\n riskReviewsDueSoon,\n ] = await Promise.all([\n forked(em).count(EudrProductMapping, { ...scope, deletedAt: null, isInScope: true }),\n forked(em).count(EudrEvidenceSubmission, { ...scope, deletedAt: null }),\n countRowsByStatus(em, EudrEvidenceSubmission, EUDR_SUBMISSION_STATUSES, scope),\n fetchAverageCompleteness(forked(em), scope),\n forked(em).count(EudrEvidenceSubmission, {\n ...scope,\n deletedAt: null,\n completenessScore: { $lt: 100 },\n } as FilterQuery<EudrEvidenceSubmission>),\n forked(em).count(EudrDueDiligenceStatement, { ...scope, deletedAt: null }),\n countRowsByStatus(em, EudrDueDiligenceStatement, EUDR_STATEMENT_STATUSES, scope),\n forked(em).count(EudrDueDiligenceStatement, { ...scope, deletedAt: null, status: 'draft' }),\n forked(em).count(EudrDueDiligenceStatement, {\n ...scope,\n deletedAt: null,\n status: { $in: ['submitted', 'available'] },\n referenceNumber: null,\n } as FilterQuery<EudrDueDiligenceStatement>),\n forked(em).count(EudrRiskAssessment, {\n ...scope,\n deletedAt: null,\n reviewDueAt: { $gte: now, $lte: reviewWindowEnd },\n } as FilterQuery<EudrRiskAssessment>),\n ])\n\n return {\n deadline: {\n date: EUDR_APPLICATION_DATES.largeAndMedium,\n daysLeft: daysLeft(EUDR_APPLICATION_DATES.largeAndMedium, now),\n },\n mappingsInScope,\n submissions: {\n total: submissionsTotal,\n byStatus: submissionsByStatus,\n avgCompleteness,\n incomplete,\n },\n statements: {\n total: statementsTotal,\n byStatus: statementsByStatus,\n notReady,\n missingReference,\n },\n riskReviewsDueSoon,\n }\n },\n}\n\nconst listStatementReadinessTool: EudrAiToolDefinition = {\n name: 'eudr.list_statement_readiness',\n displayName: 'List EUDR statement readiness',\n description:\n 'Checks due diligence statement export/submission readiness for one statement or the most recent non-archived statements. Use this when the operator asks whether statements are ready to submit/export, why a draft cannot move forward, what evidence is blocking a statement, or what the latest risk result says. Fields returned per item: id, title, status, commodity, readiness { ready, submissionCount, verifiedCount, completeCount, gaps [{ submissionId, status, completenessScore, missingFields }] }, latestRisk { conclusion, overallTier, reviewDueAt } or null, gateReasons as eudr.gate.* keys, and gateReasonsPlainText.',\n inputSchema: listStatementReadinessInput,\n requiredFeatures: ['eudr.statements.view', 'eudr.submissions.view', 'eudr.risk.view'],\n tags: ['read', 'eudr', 'statements', 'readiness'],\n isMutation: false,\n handler: async (rawInput, ctx) => {\n const input = listStatementReadinessInput.parse(rawInput)\n const scope = assertTenantScope(ctx)\n const em = resolveEm(ctx)\n const statementWhere: FilterQuery<EudrDueDiligenceStatement> = input.statementId\n ? {\n id: input.statementId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n }\n : {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n status: { $ne: 'archived' },\n }\n const statements = await em.find(EudrDueDiligenceStatement, statementWhere, {\n orderBy: { updatedAt: 'DESC', createdAt: 'DESC' },\n limit: input.statementId ? 1 : input.limit,\n })\n const statementIds = statements.map((statement) => statement.id)\n const submissionsByStatement = await loadSubmissionsForStatements(em, statementIds, scope)\n const latestRiskByStatement = await loadLatestAssessmentsForStatements(em, statementIds, scope)\n\n const items = await Promise.all(\n statements.map(async (statement) => {\n const submissions = submissionsByStatement.get(statement.id) ?? []\n const latestAssessment = latestRiskByStatement.get(statement.id) ?? null\n const readinessGaps = buildReadinessGaps(submissions)\n const gateSubmissions: GateSubmissionView[] = submissions.map((submission) => ({\n status: submission.status,\n completenessScore: asNumber(submission.completenessScore),\n originCountry: submission.originCountry ?? null,\n }))\n const gate = evaluateSubmissionGate({\n actorRole: statement.actorRole ?? null,\n referencedStatementsCount: Array.isArray(statement.referencedStatements)\n ? statement.referencedStatements.length\n : 0,\n submissions: gateSubmissions,\n latestAssessment: await buildGateAssessment(forked(em), latestAssessment, scope),\n })\n\n return {\n id: statement.id,\n title: statement.title,\n status: statement.status,\n commodity: statement.commodity,\n readiness: {\n ready: submissions.length > 0 && readinessGaps.length === 0,\n submissionCount: submissions.length,\n verifiedCount: submissions.filter((submission) => submission.status === 'verified').length,\n completeCount: submissions.filter((submission) => asNumber(submission.completenessScore) === 100).length,\n gaps: readinessGaps,\n },\n latestRisk: riskSummary(latestAssessment),\n gateReasons: gate.reasons.map(gateReasonKey),\n gateReasonsPlainText: gate.reasons.map(gateReasonText),\n }\n }),\n )\n\n return {\n items,\n count: items.length,\n }\n },\n}\n\nconst listEvidenceGapsTool: EudrAiToolDefinition = {\n name: 'eudr.list_evidence_gaps',\n displayName: 'List EUDR evidence gaps',\n description:\n 'Lists incomplete EUDR evidence submissions for the current tenant and organization. Use this when the operator asks what supplier evidence is missing, which submissions are incomplete, which origin countries increase risk, or where to focus cleanup. Fields returned per item: id, supplier, commodity, status, completenessScore, missingFields, originCountry, and countryRiskTier.',\n inputSchema: listEvidenceGapsInput,\n requiredFeatures: ['eudr.submissions.view'],\n tags: ['read', 'eudr', 'submissions', 'gaps'],\n isMutation: false,\n handler: async (rawInput, ctx) => {\n const input = listEvidenceGapsInput.parse(rawInput)\n const scope = assertTenantScope(ctx)\n const em = resolveEm(ctx)\n const where: FilterQuery<EudrEvidenceSubmission> = {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n completenessScore: { $lt: 100 },\n }\n if (input.commodity) where.commodity = input.commodity\n if (input.supplierEntityId) where.supplierEntityId = input.supplierEntityId\n\n const submissions = await findWithDecryption(\n em,\n EudrEvidenceSubmission,\n where,\n { orderBy: { completenessScore: 'ASC', updatedAt: 'DESC' }, limit: input.limit },\n scope,\n )\n\n return {\n items: submissions.map((submission) => ({\n id: submission.id,\n supplier: submission.supplierSnapshot?.displayName ?? null,\n commodity: submission.commodity,\n status: submission.status,\n completenessScore: asNumber(submission.completenessScore),\n missingFields: stringArray(submission.missingFields),\n originCountry: submission.originCountry ?? null,\n countryRiskTier: getCountryRiskTier(submission.originCountry ?? null),\n })),\n count: submissions.length,\n limit: input.limit,\n }\n },\n}\n\nconst checkProductScopeTool: EudrAiToolDefinition = {\n name: 'eudr.check_product_scope',\n displayName: 'Check EUDR product scope',\n description:\n 'Checks whether a product or HS code appears in EUDR Annex I scope. Use this when the operator asks if a product needs EUDR mapping, wants a commodity suggestion from an HS code, or needs to compare existing mappings against catalog HS data. Fields returned: existingMappings [{ id, commodity, isInScope, hsCode }], catalogProduct { id, name, sku, hsCode } or null, suggestedCommodity, and inAnnexScope.',\n inputSchema: checkProductScopeInput,\n requiredFeatures: ['eudr.mappings.view'],\n tags: ['read', 'eudr', 'mappings', 'scope'],\n isMutation: false,\n handler: async (rawInput, ctx) => {\n const input = checkProductScopeInput.parse(rawInput)\n const scope = assertTenantScope(ctx)\n const em = resolveEm(ctx)\n const catalogProduct = await loadCatalogProductById(ctx, input.productId)\n const existingMappings = input.productId\n ? await em.find(EudrProductMapping, {\n productId: input.productId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n } as FilterQuery<EudrProductMapping>, {\n orderBy: { createdAt: 'DESC' },\n limit: 50,\n })\n : []\n const effectiveHsCode = input.hsCode ?? catalogProduct?.hsCode ?? null\n const suggestedCommodity = suggestCommodityForHsCode(effectiveHsCode)\n\n return {\n existingMappings: existingMappings.map((mapping) => ({\n id: mapping.id,\n commodity: mapping.commodity,\n isInScope: mapping.isInScope,\n hsCode: mapping.hsCode ?? null,\n })),\n catalogProduct,\n suggestedCommodity,\n inAnnexScope: suggestedCommodity !== null,\n }\n },\n}\n\nconst getCountryRiskTool: EudrAiToolDefinition = {\n name: 'eudr.get_country_risk',\n displayName: 'Get EUDR country risk',\n description:\n 'Returns the current EUDR country-risk tier from the module reference data. Use this when the operator asks whether a specific origin country is low, standard, high, or unknown risk, or when they need the compact high-risk list. With country, returns { country, tier }. Without country, returns { high, lowCount, note } and only includes the low-risk list when includeLowList is true.',\n inputSchema: getCountryRiskInput,\n // Static, law-versioned reference data \u2014 no tenant rows are read, so this is\n // gated on the module's lowest-privilege view feature rather than submissions.\n requiredFeatures: ['eudr.mappings.view'],\n tags: ['read', 'eudr', 'country-risk', 'reference-data'],\n isMutation: false,\n handler: async (rawInput, ctx) => {\n const input = getCountryRiskInput.parse(rawInput)\n assertTenantScope(ctx)\n if (input.country) {\n return {\n country: input.country,\n tier: getCountryRiskTier(input.country),\n }\n }\n return {\n high: [...EUDR_HIGH_RISK_COUNTRIES],\n lowCount: EUDR_LOW_RISK_COUNTRIES.length,\n ...(input.includeLowList === true ? { low: [...EUDR_LOW_RISK_COUNTRIES] } : {}),\n note: 'Unlisted countries are standard risk.',\n }\n },\n}\n\nexport const eudrComplianceAiTools: EudrAiToolDefinition[] = [\n getComplianceOverviewTool,\n listStatementReadinessTool,\n listEvidenceGapsTool,\n checkProductScopeTool,\n getCountryRiskTool,\n]\n\nexport default eudrComplianceAiTools\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ function assertTenantScope(ctx) {
2
+ if (!ctx.tenantId || !ctx.organizationId) {
3
+ throw new Error("[internal] Tenant and organization context is required for eudr.* tools");
4
+ }
5
+ return { tenantId: ctx.tenantId, organizationId: ctx.organizationId };
6
+ }
7
+ export {
8
+ assertTenantScope
9
+ };
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/ai-tools/types.ts"],
4
+ "sourcesContent": ["/**\n * Local AI tool shape for the EUDR module.\n *\n * Mirrors the catalog module pattern: keep the module contribution as plain\n * serializable tool objects so the generator can discover them without adding\n * runtime AI assistant imports to the core module graph.\n */\nimport type { AwilixContainer } from 'awilix'\nimport type { z } from 'zod'\n\nexport interface EudrToolContext {\n tenantId: string | null\n organizationId: string | null\n userId: string | null\n container: AwilixContainer\n userFeatures: string[]\n isSuperAdmin: boolean\n apiKeySecret?: string\n sessionId?: string\n}\n\nexport interface EudrAiToolDefinition<TInput = unknown, TOutput = unknown> {\n name: string\n displayName?: string\n description: string\n inputSchema: z.ZodType<TInput>\n requiredFeatures?: string[]\n tags?: string[]\n isMutation?: boolean\n isBulk?: boolean\n maxCallsPerTurn?: number\n supportsAttachments?: boolean\n handler: (input: TInput, context: EudrToolContext) => Promise<TOutput>\n}\n\nexport function assertTenantScope(ctx: EudrToolContext): {\n tenantId: string\n organizationId: string\n} {\n if (!ctx.tenantId || !ctx.organizationId) {\n throw new Error('[internal] Tenant and organization context is required for eudr.* tools')\n }\n return { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n}\n"],
5
+ "mappings": "AAmCO,SAAS,kBAAkB,KAGhC;AACA,MAAI,CAAC,IAAI,YAAY,CAAC,IAAI,gBAAgB;AACxC,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC3F;AACA,SAAO,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AACtE;",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ import eudrComplianceAiTools from "./ai-tools/compliance-pack.js";
2
+ const aiTools = [
3
+ ...eudrComplianceAiTools
4
+ ];
5
+ var ai_tools_default = aiTools;
6
+ export {
7
+ aiTools,
8
+ ai_tools_default as default
9
+ };
10
+ //# sourceMappingURL=ai-tools.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/eudr/ai-tools.ts"],
4
+ "sourcesContent": ["/**\n * Module-root AI tool contribution for the EUDR module.\n *\n * The generator discovers this file and aggregates the read-only compliance\n * pack into the global AI tool registry. The pack exposes scoped EUDR\n * readiness, evidence-gap, product-scope, and country-risk tools only.\n */\nimport eudrComplianceAiTools from './ai-tools/compliance-pack'\nimport type { EudrAiToolDefinition } from './ai-tools/types'\n\nexport const aiTools: EudrAiToolDefinition[] = [\n ...eudrComplianceAiTools,\n]\n\nexport default aiTools\n"],
5
+ "mappings": "AAOA,OAAO,2BAA2B;AAG3B,MAAM,UAAkC;AAAA,EAC7C,GAAG;AACL;AAEA,IAAO,mBAAQ;",
6
+ "names": []
7
+ }