@kelpie/server 0.8.0 → 0.10.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/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/ids.d.ts +11 -0
  6. package/dist/lib/ids.d.ts.map +1 -1
  7. package/dist/lib/ids.js +11 -0
  8. package/dist/lib/ids.js.map +1 -1
  9. package/dist/modules/activities/repository.d.ts.map +1 -1
  10. package/dist/modules/activities/repository.js +19 -20
  11. package/dist/modules/activities/repository.js.map +1 -1
  12. package/dist/modules/activities/wording.d.ts +12 -0
  13. package/dist/modules/activities/wording.d.ts.map +1 -1
  14. package/dist/modules/activities/wording.js +16 -0
  15. package/dist/modules/activities/wording.js.map +1 -1
  16. package/dist/modules/agent-tasks/catalog.d.ts.map +1 -1
  17. package/dist/modules/agent-tasks/catalog.js +62 -0
  18. package/dist/modules/agent-tasks/catalog.js.map +1 -1
  19. package/dist/modules/agent-tasks/resolve.d.ts.map +1 -1
  20. package/dist/modules/agent-tasks/resolve.js +42 -9
  21. package/dist/modules/agent-tasks/resolve.js.map +1 -1
  22. package/dist/modules/agent-tasks/routes.d.ts +2 -0
  23. package/dist/modules/agent-tasks/routes.d.ts.map +1 -1
  24. package/dist/modules/attachedRecords.d.ts +6 -1
  25. package/dist/modules/attachedRecords.d.ts.map +1 -1
  26. package/dist/modules/attachedRecords.js +15 -1
  27. package/dist/modules/attachedRecords.js.map +1 -1
  28. package/dist/modules/companies/index.d.ts.map +1 -1
  29. package/dist/modules/companies/index.js +3 -1
  30. package/dist/modules/companies/index.js.map +1 -1
  31. package/dist/modules/companies/routes.d.ts +14 -0
  32. package/dist/modules/companies/routes.d.ts.map +1 -1
  33. package/dist/modules/companies/routes.js +7 -0
  34. package/dist/modules/companies/routes.js.map +1 -1
  35. package/dist/modules/companies/schema.d.ts +20 -0
  36. package/dist/modules/companies/schema.d.ts.map +1 -1
  37. package/dist/modules/companies/schema.js +6 -1
  38. package/dist/modules/companies/schema.js.map +1 -1
  39. package/dist/modules/companies/service.d.ts +5 -0
  40. package/dist/modules/companies/service.d.ts.map +1 -1
  41. package/dist/modules/companies/service.js +24 -12
  42. package/dist/modules/companies/service.js.map +1 -1
  43. package/dist/modules/consent-purposes/capabilities.d.ts +7 -0
  44. package/dist/modules/consent-purposes/capabilities.d.ts.map +1 -0
  45. package/dist/modules/consent-purposes/capabilities.js +10 -0
  46. package/dist/modules/consent-purposes/capabilities.js.map +1 -0
  47. package/dist/modules/consent-purposes/events.d.ts +38 -0
  48. package/dist/modules/consent-purposes/events.d.ts.map +1 -0
  49. package/dist/modules/consent-purposes/events.js +17 -0
  50. package/dist/modules/consent-purposes/events.js.map +1 -0
  51. package/dist/modules/consent-purposes/index.d.ts +13 -0
  52. package/dist/modules/consent-purposes/index.d.ts.map +1 -0
  53. package/dist/modules/consent-purposes/index.js +41 -0
  54. package/dist/modules/consent-purposes/index.js.map +1 -0
  55. package/dist/modules/consent-purposes/repository.d.ts +21 -0
  56. package/dist/modules/consent-purposes/repository.d.ts.map +1 -0
  57. package/dist/modules/consent-purposes/repository.js +98 -0
  58. package/dist/modules/consent-purposes/repository.js.map +1 -0
  59. package/dist/modules/consent-purposes/routes.d.ts +39 -0
  60. package/dist/modules/consent-purposes/routes.d.ts.map +1 -0
  61. package/dist/modules/consent-purposes/routes.js +79 -0
  62. package/dist/modules/consent-purposes/routes.js.map +1 -0
  63. package/dist/modules/consent-purposes/schema.d.ts +175 -0
  64. package/dist/modules/consent-purposes/schema.d.ts.map +1 -0
  65. package/dist/modules/consent-purposes/schema.js +35 -0
  66. package/dist/modules/consent-purposes/schema.js.map +1 -0
  67. package/dist/modules/consent-purposes/service.d.ts +50 -0
  68. package/dist/modules/consent-purposes/service.d.ts.map +1 -0
  69. package/dist/modules/consent-purposes/service.js +263 -0
  70. package/dist/modules/consent-purposes/service.js.map +1 -0
  71. package/dist/modules/consent-purposes/starters.d.ts +17 -0
  72. package/dist/modules/consent-purposes/starters.d.ts.map +1 -0
  73. package/dist/modules/consent-purposes/starters.js +15 -0
  74. package/dist/modules/consent-purposes/starters.js.map +1 -0
  75. package/dist/modules/consent-purposes/tools.d.ts +4 -0
  76. package/dist/modules/consent-purposes/tools.d.ts.map +1 -0
  77. package/dist/modules/consent-purposes/tools.js +29 -0
  78. package/dist/modules/consent-purposes/tools.js.map +1 -0
  79. package/dist/modules/core.d.ts.map +1 -1
  80. package/dist/modules/core.js +10 -0
  81. package/dist/modules/core.js.map +1 -1
  82. package/dist/modules/custom-fields/capabilities.d.ts +12 -0
  83. package/dist/modules/custom-fields/capabilities.d.ts.map +1 -0
  84. package/dist/modules/custom-fields/capabilities.js +15 -0
  85. package/dist/modules/custom-fields/capabilities.js.map +1 -0
  86. package/dist/modules/custom-fields/events.d.ts +49 -0
  87. package/dist/modules/custom-fields/events.d.ts.map +1 -0
  88. package/dist/modules/custom-fields/events.js +25 -0
  89. package/dist/modules/custom-fields/events.js.map +1 -0
  90. package/dist/modules/custom-fields/index.d.ts +19 -0
  91. package/dist/modules/custom-fields/index.d.ts.map +1 -0
  92. package/dist/modules/custom-fields/index.js +46 -0
  93. package/dist/modules/custom-fields/index.js.map +1 -0
  94. package/dist/modules/custom-fields/repository.d.ts +37 -0
  95. package/dist/modules/custom-fields/repository.d.ts.map +1 -0
  96. package/dist/modules/custom-fields/repository.js +144 -0
  97. package/dist/modules/custom-fields/repository.js.map +1 -0
  98. package/dist/modules/custom-fields/routes.d.ts +44 -0
  99. package/dist/modules/custom-fields/routes.d.ts.map +1 -0
  100. package/dist/modules/custom-fields/routes.js +103 -0
  101. package/dist/modules/custom-fields/routes.js.map +1 -0
  102. package/dist/modules/custom-fields/schema.d.ts +215 -0
  103. package/dist/modules/custom-fields/schema.d.ts.map +1 -0
  104. package/dist/modules/custom-fields/schema.js +43 -0
  105. package/dist/modules/custom-fields/schema.js.map +1 -0
  106. package/dist/modules/custom-fields/service.d.ts +57 -0
  107. package/dist/modules/custom-fields/service.d.ts.map +1 -0
  108. package/dist/modules/custom-fields/service.js +273 -0
  109. package/dist/modules/custom-fields/service.js.map +1 -0
  110. package/dist/modules/custom-fields/tools.d.ts +4 -0
  111. package/dist/modules/custom-fields/tools.d.ts.map +1 -0
  112. package/dist/modules/custom-fields/tools.js +38 -0
  113. package/dist/modules/custom-fields/tools.js.map +1 -0
  114. package/dist/modules/custom-fields/values.d.ts +49 -0
  115. package/dist/modules/custom-fields/values.d.ts.map +1 -0
  116. package/dist/modules/custom-fields/values.js +249 -0
  117. package/dist/modules/custom-fields/values.js.map +1 -0
  118. package/dist/modules/custom-fields/wire.d.ts +12 -0
  119. package/dist/modules/custom-fields/wire.d.ts.map +1 -0
  120. package/dist/modules/custom-fields/wire.js +30 -0
  121. package/dist/modules/custom-fields/wire.js.map +1 -0
  122. package/dist/modules/dashboard/repository.d.ts.map +1 -1
  123. package/dist/modules/dashboard/repository.js +4 -3
  124. package/dist/modules/dashboard/repository.js.map +1 -1
  125. package/dist/modules/deals/index.d.ts +2 -1
  126. package/dist/modules/deals/index.d.ts.map +1 -1
  127. package/dist/modules/deals/index.js +5 -2
  128. package/dist/modules/deals/index.js.map +1 -1
  129. package/dist/modules/deals/repository.d.ts +0 -16
  130. package/dist/modules/deals/repository.d.ts.map +1 -1
  131. package/dist/modules/deals/repository.js +6 -76
  132. package/dist/modules/deals/repository.js.map +1 -1
  133. package/dist/modules/deals/routes.d.ts +14 -0
  134. package/dist/modules/deals/routes.d.ts.map +1 -1
  135. package/dist/modules/deals/routes.js +7 -0
  136. package/dist/modules/deals/routes.js.map +1 -1
  137. package/dist/modules/deals/schema.d.ts +20 -42
  138. package/dist/modules/deals/schema.d.ts.map +1 -1
  139. package/dist/modules/deals/schema.js +6 -11
  140. package/dist/modules/deals/schema.js.map +1 -1
  141. package/dist/modules/deals/service.d.ts +13 -2
  142. package/dist/modules/deals/service.d.ts.map +1 -1
  143. package/dist/modules/deals/service.js +43 -20
  144. package/dist/modules/deals/service.js.map +1 -1
  145. package/dist/modules/decisions/repository.d.ts.map +1 -1
  146. package/dist/modules/decisions/repository.js +2 -0
  147. package/dist/modules/decisions/repository.js.map +1 -1
  148. package/dist/modules/decisions/routes.d.ts +1 -0
  149. package/dist/modules/decisions/routes.d.ts.map +1 -1
  150. package/dist/modules/enquiries/events.d.ts +44 -0
  151. package/dist/modules/enquiries/events.d.ts.map +1 -0
  152. package/dist/modules/enquiries/events.js +19 -0
  153. package/dist/modules/enquiries/events.js.map +1 -0
  154. package/dist/modules/enquiries/index.d.ts +13 -0
  155. package/dist/modules/enquiries/index.d.ts.map +1 -0
  156. package/dist/modules/enquiries/index.js +44 -0
  157. package/dist/modules/enquiries/index.js.map +1 -0
  158. package/dist/modules/enquiries/repository.d.ts +30 -0
  159. package/dist/modules/enquiries/repository.d.ts.map +1 -0
  160. package/dist/modules/enquiries/repository.js +94 -0
  161. package/dist/modules/enquiries/repository.js.map +1 -0
  162. package/dist/modules/enquiries/routes.d.ts +52 -0
  163. package/dist/modules/enquiries/routes.d.ts.map +1 -0
  164. package/dist/modules/enquiries/routes.js +127 -0
  165. package/dist/modules/enquiries/routes.js.map +1 -0
  166. package/dist/modules/enquiries/schema.d.ts +290 -0
  167. package/dist/modules/enquiries/schema.d.ts.map +1 -0
  168. package/dist/modules/enquiries/schema.js +52 -0
  169. package/dist/modules/enquiries/schema.js.map +1 -0
  170. package/dist/modules/enquiries/service.d.ts +85 -0
  171. package/dist/modules/enquiries/service.d.ts.map +1 -0
  172. package/dist/modules/enquiries/service.js +370 -0
  173. package/dist/modules/enquiries/service.js.map +1 -0
  174. package/dist/modules/enquiries/tools.d.ts +4 -0
  175. package/dist/modules/enquiries/tools.d.ts.map +1 -0
  176. package/dist/modules/enquiries/tools.js +50 -0
  177. package/dist/modules/enquiries/tools.js.map +1 -0
  178. package/dist/modules/eventCatalogs.d.ts +3 -0
  179. package/dist/modules/eventCatalogs.d.ts.map +1 -1
  180. package/dist/modules/eventCatalogs.js +3 -0
  181. package/dist/modules/eventCatalogs.js.map +1 -1
  182. package/dist/modules/forms/embed.d.ts +20 -6
  183. package/dist/modules/forms/embed.d.ts.map +1 -1
  184. package/dist/modules/forms/embed.js +359 -43
  185. package/dist/modules/forms/embed.js.map +1 -1
  186. package/dist/modules/forms/events.d.ts +20 -7
  187. package/dist/modules/forms/events.d.ts.map +1 -1
  188. package/dist/modules/forms/events.js +20 -2
  189. package/dist/modules/forms/events.js.map +1 -1
  190. package/dist/modules/forms/fields.d.ts +14 -1
  191. package/dist/modules/forms/fields.d.ts.map +1 -1
  192. package/dist/modules/forms/fields.js +87 -3
  193. package/dist/modules/forms/fields.js.map +1 -1
  194. package/dist/modules/forms/index.d.ts.map +1 -1
  195. package/dist/modules/forms/index.js +12 -1
  196. package/dist/modules/forms/index.js.map +1 -1
  197. package/dist/modules/forms/mapping.d.ts +62 -5
  198. package/dist/modules/forms/mapping.d.ts.map +1 -1
  199. package/dist/modules/forms/mapping.js +139 -5
  200. package/dist/modules/forms/mapping.js.map +1 -1
  201. package/dist/modules/forms/publicRoutes.d.ts.map +1 -1
  202. package/dist/modules/forms/publicRoutes.js +29 -1
  203. package/dist/modules/forms/publicRoutes.js.map +1 -1
  204. package/dist/modules/forms/repository.d.ts +31 -0
  205. package/dist/modules/forms/repository.d.ts.map +1 -1
  206. package/dist/modules/forms/repository.js +90 -1
  207. package/dist/modules/forms/repository.js.map +1 -1
  208. package/dist/modules/forms/routes.d.ts +83 -1
  209. package/dist/modules/forms/routes.d.ts.map +1 -1
  210. package/dist/modules/forms/routes.js +185 -2
  211. package/dist/modules/forms/routes.js.map +1 -1
  212. package/dist/modules/forms/schema.d.ts +672 -1
  213. package/dist/modules/forms/schema.d.ts.map +1 -1
  214. package/dist/modules/forms/schema.js +146 -3
  215. package/dist/modules/forms/schema.js.map +1 -1
  216. package/dist/modules/forms/service.d.ts +54 -1
  217. package/dist/modules/forms/service.d.ts.map +1 -1
  218. package/dist/modules/forms/service.js +338 -28
  219. package/dist/modules/forms/service.js.map +1 -1
  220. package/dist/modules/forms/submission.d.ts +15 -0
  221. package/dist/modules/forms/submission.d.ts.map +1 -1
  222. package/dist/modules/forms/submission.js +418 -40
  223. package/dist/modules/forms/submission.js.map +1 -1
  224. package/dist/modules/import-export/drafts.d.ts +10 -0
  225. package/dist/modules/import-export/drafts.d.ts.map +1 -1
  226. package/dist/modules/import-export/drafts.js +16 -2
  227. package/dist/modules/import-export/drafts.js.map +1 -1
  228. package/dist/modules/import-export/exportRows.d.ts +7 -4
  229. package/dist/modules/import-export/exportRows.d.ts.map +1 -1
  230. package/dist/modules/import-export/exportRows.js +20 -5
  231. package/dist/modules/import-export/exportRows.js.map +1 -1
  232. package/dist/modules/import-export/plan.d.ts +12 -1
  233. package/dist/modules/import-export/plan.d.ts.map +1 -1
  234. package/dist/modules/import-export/plan.js +29 -2
  235. package/dist/modules/import-export/plan.js.map +1 -1
  236. package/dist/modules/import-export/presets.d.ts.map +1 -1
  237. package/dist/modules/import-export/presets.js +10 -0
  238. package/dist/modules/import-export/presets.js.map +1 -1
  239. package/dist/modules/import-export/repository.d.ts +11 -1
  240. package/dist/modules/import-export/repository.d.ts.map +1 -1
  241. package/dist/modules/import-export/repository.js +42 -9
  242. package/dist/modules/import-export/repository.js.map +1 -1
  243. package/dist/modules/import-export/routes.d.ts.map +1 -1
  244. package/dist/modules/import-export/routes.js +4 -0
  245. package/dist/modules/import-export/routes.js.map +1 -1
  246. package/dist/modules/import-export/schema.d.ts +17 -0
  247. package/dist/modules/import-export/schema.d.ts.map +1 -1
  248. package/dist/modules/import-export/schema.js +11 -0
  249. package/dist/modules/import-export/schema.js.map +1 -1
  250. package/dist/modules/import-export/service.d.ts +6 -0
  251. package/dist/modules/import-export/service.d.ts.map +1 -1
  252. package/dist/modules/import-export/service.js +14 -2
  253. package/dist/modules/import-export/service.js.map +1 -1
  254. package/dist/modules/import-export/streams.d.ts.map +1 -1
  255. package/dist/modules/import-export/streams.js +3 -3
  256. package/dist/modules/import-export/streams.js.map +1 -1
  257. package/dist/modules/import-export/tools.d.ts.map +1 -1
  258. package/dist/modules/import-export/tools.js +8 -0
  259. package/dist/modules/import-export/tools.js.map +1 -1
  260. package/dist/modules/import-export/validation.d.ts.map +1 -1
  261. package/dist/modules/import-export/validation.js +22 -1
  262. package/dist/modules/import-export/validation.js.map +1 -1
  263. package/dist/modules/import-export/writes.d.ts.map +1 -1
  264. package/dist/modules/import-export/writes.js +37 -4
  265. package/dist/modules/import-export/writes.js.map +1 -1
  266. package/dist/modules/lists/index.d.ts +38 -0
  267. package/dist/modules/lists/index.d.ts.map +1 -1
  268. package/dist/modules/lists/index.js +27 -0
  269. package/dist/modules/lists/index.js.map +1 -1
  270. package/dist/modules/lists/repository.d.ts +26 -0
  271. package/dist/modules/lists/repository.d.ts.map +1 -1
  272. package/dist/modules/lists/repository.js +32 -0
  273. package/dist/modules/lists/repository.js.map +1 -1
  274. package/dist/modules/lists/routes.d.ts +4 -0
  275. package/dist/modules/lists/routes.d.ts.map +1 -1
  276. package/dist/modules/lists/routes.js +8 -0
  277. package/dist/modules/lists/routes.js.map +1 -1
  278. package/dist/modules/lists/schema.d.ts +17 -0
  279. package/dist/modules/lists/schema.d.ts.map +1 -1
  280. package/dist/modules/lists/schema.js +10 -0
  281. package/dist/modules/lists/schema.js.map +1 -1
  282. package/dist/modules/lists/service.d.ts +14 -2
  283. package/dist/modules/lists/service.d.ts.map +1 -1
  284. package/dist/modules/lists/service.js +55 -7
  285. package/dist/modules/lists/service.js.map +1 -1
  286. package/dist/modules/mcp/index.d.ts.map +1 -1
  287. package/dist/modules/mcp/index.js +5 -0
  288. package/dist/modules/mcp/index.js.map +1 -1
  289. package/dist/modules/notes/routes.d.ts +1 -0
  290. package/dist/modules/notes/routes.d.ts.map +1 -1
  291. package/dist/modules/opportunities/index.d.ts.map +1 -1
  292. package/dist/modules/opportunities/index.js +3 -1
  293. package/dist/modules/opportunities/index.js.map +1 -1
  294. package/dist/modules/opportunities/repository.d.ts +2 -0
  295. package/dist/modules/opportunities/repository.d.ts.map +1 -1
  296. package/dist/modules/opportunities/repository.js +4 -0
  297. package/dist/modules/opportunities/repository.js.map +1 -1
  298. package/dist/modules/opportunities/routes.d.ts +16 -0
  299. package/dist/modules/opportunities/routes.d.ts.map +1 -1
  300. package/dist/modules/opportunities/routes.js +13 -0
  301. package/dist/modules/opportunities/routes.js.map +1 -1
  302. package/dist/modules/opportunities/schema.d.ts +20 -0
  303. package/dist/modules/opportunities/schema.d.ts.map +1 -1
  304. package/dist/modules/opportunities/schema.js +6 -1
  305. package/dist/modules/opportunities/schema.js.map +1 -1
  306. package/dist/modules/opportunities/service.d.ts +20 -3
  307. package/dist/modules/opportunities/service.d.ts.map +1 -1
  308. package/dist/modules/opportunities/service.js +99 -18
  309. package/dist/modules/opportunities/service.js.map +1 -1
  310. package/dist/modules/opportunities/tools.d.ts.map +1 -1
  311. package/dist/modules/opportunities/tools.js +2 -0
  312. package/dist/modules/opportunities/tools.js.map +1 -1
  313. package/dist/modules/partnerships/index.d.ts.map +1 -1
  314. package/dist/modules/partnerships/index.js +3 -1
  315. package/dist/modules/partnerships/index.js.map +1 -1
  316. package/dist/modules/partnerships/repository.d.ts +0 -17
  317. package/dist/modules/partnerships/repository.d.ts.map +1 -1
  318. package/dist/modules/partnerships/repository.js +6 -82
  319. package/dist/modules/partnerships/repository.js.map +1 -1
  320. package/dist/modules/partnerships/routes.d.ts +14 -0
  321. package/dist/modules/partnerships/routes.d.ts.map +1 -1
  322. package/dist/modules/partnerships/routes.js +7 -0
  323. package/dist/modules/partnerships/routes.js.map +1 -1
  324. package/dist/modules/partnerships/schema.d.ts +20 -41
  325. package/dist/modules/partnerships/schema.d.ts.map +1 -1
  326. package/dist/modules/partnerships/schema.js +6 -10
  327. package/dist/modules/partnerships/schema.js.map +1 -1
  328. package/dist/modules/partnerships/service.d.ts +11 -1
  329. package/dist/modules/partnerships/service.d.ts.map +1 -1
  330. package/dist/modules/partnerships/service.js +43 -20
  331. package/dist/modules/partnerships/service.js.map +1 -1
  332. package/dist/modules/people/consentHydration.d.ts +26 -0
  333. package/dist/modules/people/consentHydration.d.ts.map +1 -0
  334. package/dist/modules/people/consentHydration.js +100 -0
  335. package/dist/modules/people/consentHydration.js.map +1 -0
  336. package/dist/modules/people/index.d.ts.map +1 -1
  337. package/dist/modules/people/index.js +3 -1
  338. package/dist/modules/people/index.js.map +1 -1
  339. package/dist/modules/people/personConsentWrites.d.ts +40 -0
  340. package/dist/modules/people/personConsentWrites.d.ts.map +1 -0
  341. package/dist/modules/people/personConsentWrites.js +98 -0
  342. package/dist/modules/people/personConsentWrites.js.map +1 -0
  343. package/dist/modules/people/repository.d.ts.map +1 -1
  344. package/dist/modules/people/repository.js +5 -1
  345. package/dist/modules/people/repository.js.map +1 -1
  346. package/dist/modules/people/routes.d.ts +57 -4
  347. package/dist/modules/people/routes.d.ts.map +1 -1
  348. package/dist/modules/people/routes.js +104 -5
  349. package/dist/modules/people/routes.js.map +1 -1
  350. package/dist/modules/people/schema.d.ts +366 -1
  351. package/dist/modules/people/schema.d.ts.map +1 -1
  352. package/dist/modules/people/schema.js +92 -2
  353. package/dist/modules/people/schema.js.map +1 -1
  354. package/dist/modules/people/service.d.ts +30 -1
  355. package/dist/modules/people/service.d.ts.map +1 -1
  356. package/dist/modules/people/service.js +115 -38
  357. package/dist/modules/people/service.js.map +1 -1
  358. package/dist/modules/people/tools.d.ts.map +1 -1
  359. package/dist/modules/people/tools.js +4 -1
  360. package/dist/modules/people/tools.js.map +1 -1
  361. package/dist/modules/personLinks.d.ts +79 -0
  362. package/dist/modules/personLinks.d.ts.map +1 -0
  363. package/dist/modules/personLinks.js +155 -0
  364. package/dist/modules/personLinks.js.map +1 -0
  365. package/dist/modules/pipelines/routes.d.ts +1 -0
  366. package/dist/modules/pipelines/routes.d.ts.map +1 -1
  367. package/dist/modules/plans/routes.d.ts +1 -0
  368. package/dist/modules/plans/routes.d.ts.map +1 -1
  369. package/dist/modules/raises/index.d.ts.map +1 -1
  370. package/dist/modules/raises/index.js +3 -1
  371. package/dist/modules/raises/index.js.map +1 -1
  372. package/dist/modules/raises/repository.d.ts +0 -17
  373. package/dist/modules/raises/repository.d.ts.map +1 -1
  374. package/dist/modules/raises/repository.js +6 -77
  375. package/dist/modules/raises/repository.js.map +1 -1
  376. package/dist/modules/raises/routes.d.ts +14 -0
  377. package/dist/modules/raises/routes.d.ts.map +1 -1
  378. package/dist/modules/raises/routes.js +7 -0
  379. package/dist/modules/raises/routes.js.map +1 -1
  380. package/dist/modules/raises/schema.d.ts +20 -41
  381. package/dist/modules/raises/schema.d.ts.map +1 -1
  382. package/dist/modules/raises/schema.js +6 -10
  383. package/dist/modules/raises/schema.js.map +1 -1
  384. package/dist/modules/raises/service.d.ts +11 -1
  385. package/dist/modules/raises/service.d.ts.map +1 -1
  386. package/dist/modules/raises/service.js +41 -18
  387. package/dist/modules/raises/service.js.map +1 -1
  388. package/dist/modules/recordTargets.d.ts.map +1 -1
  389. package/dist/modules/recordTargets.js +2 -0
  390. package/dist/modules/recordTargets.js.map +1 -1
  391. package/dist/modules/references.d.ts +10 -0
  392. package/dist/modules/references.d.ts.map +1 -1
  393. package/dist/modules/references.js +27 -4
  394. package/dist/modules/references.js.map +1 -1
  395. package/dist/modules/sample-data/fixture.d.ts +21 -0
  396. package/dist/modules/sample-data/fixture.d.ts.map +1 -1
  397. package/dist/modules/sample-data/fixture.js +40 -0
  398. package/dist/modules/sample-data/fixture.js.map +1 -1
  399. package/dist/modules/sample-data/index.d.ts.map +1 -1
  400. package/dist/modules/sample-data/index.js +1 -0
  401. package/dist/modules/sample-data/index.js.map +1 -1
  402. package/dist/modules/sample-data/routes.d.ts.map +1 -1
  403. package/dist/modules/sample-data/routes.js +1 -0
  404. package/dist/modules/sample-data/routes.js.map +1 -1
  405. package/dist/modules/sample-data/service.d.ts +1 -0
  406. package/dist/modules/sample-data/service.d.ts.map +1 -1
  407. package/dist/modules/sample-data/service.js +77 -8
  408. package/dist/modules/sample-data/service.js.map +1 -1
  409. package/dist/modules/search/index.d.ts +1 -1
  410. package/dist/modules/search/index.d.ts.map +1 -1
  411. package/dist/modules/search/index.js +2 -1
  412. package/dist/modules/search/index.js.map +1 -1
  413. package/dist/modules/search/repository.d.ts +1 -0
  414. package/dist/modules/search/repository.d.ts.map +1 -1
  415. package/dist/modules/search/repository.js +23 -0
  416. package/dist/modules/search/repository.js.map +1 -1
  417. package/dist/modules/search/service.d.ts +3 -3
  418. package/dist/modules/search/service.d.ts.map +1 -1
  419. package/dist/modules/search/service.js +5 -4
  420. package/dist/modules/search/service.js.map +1 -1
  421. package/dist/modules/stagedRecords.d.ts +3 -3
  422. package/dist/modules/stagedRecords.d.ts.map +1 -1
  423. package/dist/modules/stagedRecords.js +9 -0
  424. package/dist/modules/stagedRecords.js.map +1 -1
  425. package/dist/modules/webhooks/payloads.d.ts.map +1 -1
  426. package/dist/modules/webhooks/payloads.js +15 -2
  427. package/dist/modules/webhooks/payloads.js.map +1 -1
  428. package/dist/modules/workspace/repository.d.ts +2 -0
  429. package/dist/modules/workspace/repository.d.ts.map +1 -1
  430. package/dist/modules/workspace/repository.js +7 -0
  431. package/dist/modules/workspace/repository.js.map +1 -1
  432. package/dist/modules/workspace/service.d.ts.map +1 -1
  433. package/dist/modules/workspace/service.js +10 -0
  434. package/dist/modules/workspace/service.js.map +1 -1
  435. package/dist/modules/workspace/starters.d.ts.map +1 -1
  436. package/dist/modules/workspace/starters.js +5 -0
  437. package/dist/modules/workspace/starters.js.map +1 -1
  438. package/dist/runtime/events.d.ts +1 -1
  439. package/dist/runtime/events.d.ts.map +1 -1
  440. package/dist/runtime/events.js +1 -0
  441. package/dist/runtime/events.js.map +1 -1
  442. package/dist/schema/index.d.ts +3 -0
  443. package/dist/schema/index.d.ts.map +1 -1
  444. package/dist/schema/index.js +3 -0
  445. package/dist/schema/index.js.map +1 -1
  446. package/dist/testing/database.d.ts +5 -1
  447. package/dist/testing/database.d.ts.map +1 -1
  448. package/dist/testing/database.js +81 -10
  449. package/dist/testing/database.js.map +1 -1
  450. package/migrations/0024_third_king_cobra.sql +46 -0
  451. package/migrations/0025_worthless_chimera.sql +3 -0
  452. package/migrations/0026_late_aqueduct.sql +46 -0
  453. package/migrations/0027_brainy_silver_sable.sql +3 -0
  454. package/migrations/0028_freezing_scrambler.sql +19 -0
  455. package/migrations/0029_custom_fields.sql +26 -0
  456. package/migrations/0030_enquiries.sql +79 -0
  457. package/migrations/0031_consent.sql +45 -0
  458. package/migrations/0032_form_field_statement.sql +1 -0
  459. package/migrations/0033_form_field_consent_purpose_ids.sql +5 -0
  460. package/migrations/0034_drop_form_field_consent_purpose_id.sql +1 -0
  461. package/migrations/0035_form_field_consent_purpose_labels.sql +1 -0
  462. package/migrations/0036_form_field_notice_type.sql +2 -0
  463. package/migrations/meta/0024_snapshot.json +5516 -0
  464. package/migrations/meta/0025_snapshot.json +5336 -0
  465. package/migrations/meta/0026_snapshot.json +5710 -0
  466. package/migrations/meta/0027_snapshot.json +5716 -0
  467. package/migrations/meta/0028_snapshot.json +5740 -0
  468. package/migrations/meta/0029_snapshot.json +5935 -0
  469. package/migrations/meta/0030_snapshot.json +6245 -0
  470. package/migrations/meta/0031_snapshot.json +6572 -0
  471. package/migrations/meta/0032_snapshot.json +6578 -0
  472. package/migrations/meta/0033_snapshot.json +6572 -0
  473. package/migrations/meta/0034_snapshot.json +6566 -0
  474. package/migrations/meta/0035_snapshot.json +6573 -0
  475. package/migrations/meta/0036_snapshot.json +6573 -0
  476. package/migrations/meta/_journal.json +91 -0
  477. package/package.json +2 -2
  478. package/src/index.ts +6 -0
  479. package/src/lib/ids.ts +11 -0
  480. package/src/modules/activities/repository.ts +22 -23
  481. package/src/modules/activities/wording.ts +18 -0
  482. package/src/modules/agent-tasks/catalog.ts +63 -0
  483. package/src/modules/agent-tasks/resolve.ts +64 -24
  484. package/src/modules/attachedRecords.ts +29 -2
  485. package/src/modules/companies/index.ts +3 -1
  486. package/src/modules/companies/routes.ts +7 -0
  487. package/src/modules/companies/schema.ts +7 -1
  488. package/src/modules/companies/service.ts +48 -13
  489. package/src/modules/consent-purposes/capabilities.ts +12 -0
  490. package/src/modules/consent-purposes/events.ts +38 -0
  491. package/src/modules/consent-purposes/index.ts +48 -0
  492. package/src/modules/consent-purposes/repository.ts +163 -0
  493. package/src/modules/consent-purposes/routes.ts +122 -0
  494. package/src/modules/consent-purposes/schema.ts +46 -0
  495. package/src/modules/consent-purposes/service.ts +423 -0
  496. package/src/modules/consent-purposes/starters.ts +32 -0
  497. package/src/modules/consent-purposes/tools.ts +44 -0
  498. package/src/modules/core.ts +10 -0
  499. package/src/modules/custom-fields/capabilities.ts +17 -0
  500. package/src/modules/custom-fields/events.ts +51 -0
  501. package/src/modules/custom-fields/index.ts +61 -0
  502. package/src/modules/custom-fields/repository.ts +225 -0
  503. package/src/modules/custom-fields/routes.ts +155 -0
  504. package/src/modules/custom-fields/schema.ts +61 -0
  505. package/src/modules/custom-fields/service.ts +439 -0
  506. package/src/modules/custom-fields/tools.ts +53 -0
  507. package/src/modules/custom-fields/values.ts +352 -0
  508. package/src/modules/custom-fields/wire.ts +32 -0
  509. package/src/modules/dashboard/repository.ts +4 -3
  510. package/src/modules/deals/index.ts +5 -2
  511. package/src/modules/deals/repository.ts +6 -106
  512. package/src/modules/deals/routes.ts +7 -0
  513. package/src/modules/deals/schema.ts +7 -15
  514. package/src/modules/deals/service.ts +92 -23
  515. package/src/modules/decisions/repository.ts +2 -0
  516. package/src/modules/enquiries/events.ts +45 -0
  517. package/src/modules/enquiries/index.ts +50 -0
  518. package/src/modules/enquiries/repository.ts +164 -0
  519. package/src/modules/enquiries/routes.ts +172 -0
  520. package/src/modules/enquiries/schema.ts +59 -0
  521. package/src/modules/enquiries/service.ts +644 -0
  522. package/src/modules/enquiries/tools.ts +66 -0
  523. package/src/modules/eventCatalogs.ts +3 -0
  524. package/src/modules/forms/embed.ts +391 -44
  525. package/src/modules/forms/events.ts +30 -2
  526. package/src/modules/forms/fields.ts +102 -2
  527. package/src/modules/forms/index.ts +12 -1
  528. package/src/modules/forms/mapping.ts +183 -6
  529. package/src/modules/forms/publicRoutes.ts +43 -1
  530. package/src/modules/forms/repository.ts +162 -1
  531. package/src/modules/forms/routes.ts +212 -2
  532. package/src/modules/forms/schema.ts +166 -4
  533. package/src/modules/forms/service.ts +565 -41
  534. package/src/modules/forms/submission.ts +718 -44
  535. package/src/modules/import-export/drafts.ts +20 -1
  536. package/src/modules/import-export/exportRows.ts +21 -5
  537. package/src/modules/import-export/plan.ts +47 -2
  538. package/src/modules/import-export/presets.ts +10 -0
  539. package/src/modules/import-export/repository.ts +73 -8
  540. package/src/modules/import-export/routes.ts +4 -0
  541. package/src/modules/import-export/schema.ts +11 -0
  542. package/src/modules/import-export/service.ts +28 -2
  543. package/src/modules/import-export/streams.ts +3 -1
  544. package/src/modules/import-export/tools.ts +10 -0
  545. package/src/modules/import-export/validation.ts +28 -0
  546. package/src/modules/import-export/writes.ts +70 -5
  547. package/src/modules/lists/index.ts +71 -0
  548. package/src/modules/lists/repository.ts +64 -0
  549. package/src/modules/lists/routes.ts +8 -0
  550. package/src/modules/lists/schema.ts +10 -0
  551. package/src/modules/lists/service.ts +110 -9
  552. package/src/modules/mcp/index.ts +5 -0
  553. package/src/modules/opportunities/index.ts +3 -1
  554. package/src/modules/opportunities/repository.ts +11 -0
  555. package/src/modules/opportunities/routes.ts +13 -0
  556. package/src/modules/opportunities/schema.ts +7 -1
  557. package/src/modules/opportunities/service.ts +188 -22
  558. package/src/modules/opportunities/tools.ts +2 -0
  559. package/src/modules/partnerships/index.ts +3 -1
  560. package/src/modules/partnerships/repository.ts +6 -117
  561. package/src/modules/partnerships/routes.ts +7 -0
  562. package/src/modules/partnerships/schema.ts +7 -14
  563. package/src/modules/partnerships/service.ts +93 -22
  564. package/src/modules/people/consentHydration.ts +167 -0
  565. package/src/modules/people/index.ts +3 -1
  566. package/src/modules/people/personConsentWrites.ts +177 -0
  567. package/src/modules/people/repository.ts +5 -0
  568. package/src/modules/people/routes.ts +127 -18
  569. package/src/modules/people/schema.ts +109 -3
  570. package/src/modules/people/service.ts +186 -40
  571. package/src/modules/people/tools.ts +5 -1
  572. package/src/modules/personLinks.ts +278 -0
  573. package/src/modules/raises/index.ts +3 -1
  574. package/src/modules/raises/repository.ts +6 -107
  575. package/src/modules/raises/routes.ts +7 -0
  576. package/src/modules/raises/schema.ts +7 -14
  577. package/src/modules/raises/service.ts +91 -20
  578. package/src/modules/recordTargets.ts +2 -0
  579. package/src/modules/references.ts +43 -4
  580. package/src/modules/sample-data/fixture.ts +63 -0
  581. package/src/modules/sample-data/index.ts +1 -0
  582. package/src/modules/sample-data/routes.ts +1 -0
  583. package/src/modules/sample-data/service.ts +97 -8
  584. package/src/modules/search/index.ts +2 -1
  585. package/src/modules/search/repository.ts +33 -1
  586. package/src/modules/search/service.ts +7 -5
  587. package/src/modules/stagedRecords.ts +18 -3
  588. package/src/modules/webhooks/payloads.ts +20 -2
  589. package/src/modules/workspace/repository.ts +12 -0
  590. package/src/modules/workspace/service.ts +14 -0
  591. package/src/modules/workspace/starters.ts +5 -0
  592. package/src/runtime/events.ts +1 -0
  593. package/src/schema/index.ts +3 -0
  594. package/src/testing/database.ts +97 -11
@@ -0,0 +1,423 @@
1
+ import { CONSENT_PURPOSE_STATUSES } from '@kelpie/schemas'
2
+ import type { ConsentPurposeStatus } from '@kelpie/schemas'
3
+ import { and, eq, sql } from 'drizzle-orm'
4
+
5
+ import { toEventActor } from '../../lib/actor.ts'
6
+ import { changedKeys } from '../../lib/changes.ts'
7
+ import {
8
+ FOREIGN_KEY_VIOLATION,
9
+ UNIQUE_VIOLATION,
10
+ postgresErrorCode,
11
+ } from '../../lib/database.ts'
12
+ import type { Database } from '../../lib/database.ts'
13
+ import { AppError } from '../../lib/errors.ts'
14
+ import type { IdFactory } from '../../lib/ids.ts'
15
+ import { mapPage, readListWindow, toPage } from '../../lib/pagination.ts'
16
+ import type { ListQueryParameters, Page } from '../../lib/pagination.ts'
17
+ import type { EntitlementRegistry } from '../../runtime/entitlements.ts'
18
+ import { limitFor } from '../../runtime/entitlements.ts'
19
+ import type { Transaction, TransactionScope } from '../../runtime/transaction.ts'
20
+ import type { Actor } from '../auth/actor.ts'
21
+ import { requireWorkspaceId } from '../auth/actor.ts'
22
+ import { formFields } from '../forms/schema.ts'
23
+ import { lists } from '../lists/schema.ts'
24
+ import { roleAllows } from '../workspace/roles.ts'
25
+ import { CONSENT_PURPOSES_LIMIT } from './capabilities.ts'
26
+ import './events.ts'
27
+ import * as repository from './repository.ts'
28
+ import {
29
+ CONSENT_PURPOSE_SORTS,
30
+ DEFAULT_CONSENT_PURPOSE_SORT,
31
+ } from './repository.ts'
32
+ import type {
33
+ ConsentPurposeFilters,
34
+ ConsentPurposeRecord,
35
+ } from './repository.ts'
36
+
37
+ /**
38
+ * CRUD for the workspace's consent purposes.
39
+ *
40
+ * Reads are open to any workspace member — every capture site needs to list
41
+ * them to render its purpose picker. Writes need the admin role: a purpose
42
+ * change touches every form, list, and import job that names it, and it is
43
+ * team-wide config rather than a per-user preference.
44
+ */
45
+
46
+ /** Hard cap per workspace. Bites when the entitlement leaves the count unlimited. */
47
+ export const CONSENT_PURPOSES_HARD_CAP = 50
48
+
49
+ const KEY_PATTERN = /^[a-z][a-z0-9_]*$/u
50
+ const MAX_SLUG_LENGTH = 64
51
+ const MAX_LABEL_LENGTH = 120
52
+ const MIN_LABEL_LENGTH = 1
53
+ const MAX_DESCRIPTION_LENGTH = 2000
54
+
55
+ export interface ConsentPurposesDependencies {
56
+ readonly db: Database
57
+ readonly transaction: TransactionScope
58
+ readonly createId: IdFactory
59
+ readonly now: () => Date
60
+ readonly entitlements: EntitlementRegistry
61
+ }
62
+
63
+ /** What the API returns: the stored row minus the tenancy column. */
64
+ export type ConsentPurposeView = Omit<ConsentPurposeRecord, 'workspaceId'>
65
+
66
+ export interface CreateConsentPurposeInput {
67
+ readonly slug: string
68
+ readonly label: string
69
+ readonly description: string
70
+ readonly defaultStatus: ConsentPurposeStatus
71
+ }
72
+
73
+ /** PATCH semantics: `slug` is immutable and refused by the route body. */
74
+ export interface UpdateConsentPurposeInput {
75
+ readonly label?: string | undefined
76
+ readonly description?: string | undefined
77
+ readonly defaultStatus?: ConsentPurposeStatus | undefined
78
+ readonly sortOrder?: number | undefined
79
+ }
80
+
81
+ export interface ConsentPurposesService {
82
+ list(
83
+ actor: Actor,
84
+ filters: ConsentPurposeFilters,
85
+ query: ListQueryParameters,
86
+ ): Promise<Page<ConsentPurposeView>>
87
+ get(actor: Actor, id: string): Promise<ConsentPurposeView>
88
+ create(actor: Actor, input: CreateConsentPurposeInput): Promise<ConsentPurposeView>
89
+ update(
90
+ actor: Actor,
91
+ id: string,
92
+ changes: UpdateConsentPurposeInput,
93
+ ): Promise<ConsentPurposeView>
94
+ remove(actor: Actor, id: string): Promise<void>
95
+ }
96
+
97
+ function toView(record: ConsentPurposeRecord): ConsentPurposeView {
98
+ const { workspaceId: _workspaceId, ...view } = record
99
+ return view
100
+ }
101
+
102
+ function fieldError(field: string, message: string): AppError {
103
+ return AppError.validationFailed('That consent purpose is not valid', [{ field, message }])
104
+ }
105
+
106
+ function duplicateSlug(): AppError {
107
+ return AppError.conflict('Another consent purpose already uses that slug', [
108
+ { field: 'slug', message: 'Already in use' },
109
+ ])
110
+ }
111
+
112
+ function validateSlug(slug: string): void {
113
+ if (slug.length === 0 || slug.length > MAX_SLUG_LENGTH) {
114
+ throw fieldError('slug', `1 to ${String(MAX_SLUG_LENGTH)} characters`)
115
+ }
116
+ if (!KEY_PATTERN.test(slug)) {
117
+ throw fieldError(
118
+ 'slug',
119
+ 'Lowercase letters, digits and underscores; must start with a letter',
120
+ )
121
+ }
122
+ }
123
+
124
+ function validateLabel(label: string): void {
125
+ if (label.length < MIN_LABEL_LENGTH || label.length > MAX_LABEL_LENGTH) {
126
+ throw fieldError(
127
+ 'label',
128
+ `${String(MIN_LABEL_LENGTH)} to ${String(MAX_LABEL_LENGTH)} characters`,
129
+ )
130
+ }
131
+ }
132
+
133
+ function validateDescription(description: string): void {
134
+ if (description.length > MAX_DESCRIPTION_LENGTH) {
135
+ throw fieldError('description', `At most ${String(MAX_DESCRIPTION_LENGTH)} characters`)
136
+ }
137
+ }
138
+
139
+ function validateDefaultStatus(status: string): void {
140
+ if (!CONSENT_PURPOSE_STATUSES.includes(status as ConsentPurposeStatus)) {
141
+ throw fieldError('default_status', `Unknown status "${status}"`)
142
+ }
143
+ }
144
+
145
+ /**
146
+ * A purpose still named by a form's consent field or a list's
147
+ * `consent_purpose_id` cannot be deleted. Counted here so the 409 lists both
148
+ * types; the FK on either side would refuse the delete on its own but only
149
+ * name one.
150
+ */
151
+ async function referencingTypes(
152
+ db: Database | Transaction,
153
+ workspaceId: string,
154
+ id: string,
155
+ ): Promise<readonly string[]> {
156
+ const [fieldRow, listRow] = await Promise.all([
157
+ db
158
+ .select({ count: sql<number>`count(*)::int` })
159
+ .from(formFields)
160
+ .where(
161
+ and(
162
+ eq(formFields.workspaceId, workspaceId),
163
+ // The array contains this purpose id. A form field carries a set of
164
+ // purposes; the delete is refused if any field still lists this one.
165
+ sql`${id} = ANY(${formFields.consentPurposeIds})`,
166
+ ),
167
+ ),
168
+ db
169
+ .select({ count: sql<number>`count(*)::int` })
170
+ .from(lists)
171
+ .where(and(eq(lists.workspaceId, workspaceId), eq(lists.consentPurposeId, id))),
172
+ ])
173
+
174
+ const referencing: string[] = []
175
+ if (Number(fieldRow[0]?.count ?? 0) > 0) {
176
+ referencing.push('form_field')
177
+ }
178
+ if (Number(listRow[0]?.count ?? 0) > 0) {
179
+ referencing.push('list')
180
+ }
181
+ return referencing
182
+ }
183
+
184
+ export function createConsentPurposesService(
185
+ dependencies: ConsentPurposesDependencies,
186
+ ): ConsentPurposesService {
187
+ function requireAdminWorkspace(actor: Actor): string {
188
+ const workspaceId = requireWorkspaceId(actor)
189
+ if (actor.role === null || !roleAllows(actor.role, 'admin')) {
190
+ throw new AppError('forbidden', 'This action needs the admin role')
191
+ }
192
+ return workspaceId
193
+ }
194
+
195
+ async function require(
196
+ workspaceId: string,
197
+ id: string,
198
+ ): Promise<ConsentPurposeRecord> {
199
+ const purpose = await repository.findPurpose(dependencies.db, workspaceId, id)
200
+ if (purpose === undefined) {
201
+ throw AppError.notFound('Consent purpose not found')
202
+ }
203
+ return purpose
204
+ }
205
+
206
+ async function renumber(
207
+ tx: Transaction,
208
+ workspaceId: string,
209
+ order: readonly ConsentPurposeRecord[],
210
+ ): Promise<void> {
211
+ for (const [index, purpose] of order.entries()) {
212
+ if (purpose.sortOrder !== index) {
213
+ await repository.updatePurpose(tx, workspaceId, purpose.id, {
214
+ sortOrder: index,
215
+ updatedAt: dependencies.now(),
216
+ })
217
+ }
218
+ }
219
+ }
220
+
221
+ async function moveToPosition(
222
+ tx: Transaction,
223
+ workspaceId: string,
224
+ purpose: ConsentPurposeRecord,
225
+ position: number,
226
+ ): Promise<void> {
227
+ const rows = await repository.purposesForWorkspace(tx, workspaceId)
228
+ const target = rows.find((row) => row.id === purpose.id)
229
+ if (target === undefined) {
230
+ throw AppError.notFound('Consent purpose not found')
231
+ }
232
+ if (position < 0 || position >= rows.length) {
233
+ throw fieldError('sort_order', `Use 0 to ${String(rows.length - 1)}`)
234
+ }
235
+ const reordered = rows.filter((row) => row.id !== purpose.id)
236
+ reordered.splice(position, 0, target)
237
+ await renumber(tx, workspaceId, reordered)
238
+ }
239
+
240
+ return {
241
+ async list(actor, filters, query) {
242
+ const workspaceId = requireWorkspaceId(actor)
243
+ const window = readListWindow(query, CONSENT_PURPOSE_SORTS, DEFAULT_CONSENT_PURPOSE_SORT)
244
+ const rows = await repository.listPurposes(dependencies.db, workspaceId, filters, window)
245
+ return mapPage(toPage(rows, window, (row) => row.id), toView)
246
+ },
247
+
248
+ async get(actor, id) {
249
+ return toView(await require(requireWorkspaceId(actor), id))
250
+ },
251
+
252
+ async create(actor, input) {
253
+ const workspaceId = requireAdminWorkspace(actor)
254
+ validateSlug(input.slug)
255
+ validateLabel(input.label)
256
+ validateDescription(input.description)
257
+ validateDefaultStatus(input.defaultStatus)
258
+
259
+ const limit = await limitFor(
260
+ dependencies.entitlements,
261
+ workspaceId,
262
+ CONSENT_PURPOSES_LIMIT.name,
263
+ )
264
+ if (limit !== null) {
265
+ const total = await repository.countPurposes(dependencies.db, workspaceId)
266
+ if (total >= limit) {
267
+ throw new AppError(
268
+ 'entitlement_required',
269
+ `Your plan allows ${String(limit)} consent purpose${limit === 1 ? '' : 's'}`,
270
+ )
271
+ }
272
+ }
273
+
274
+ const id = dependencies.createId('consentPurpose')
275
+
276
+ return dependencies.transaction(
277
+ async ({ tx, events }) => {
278
+ const existing = await repository.purposesForWorkspace(tx, workspaceId)
279
+ if (existing.length >= CONSENT_PURPOSES_HARD_CAP) {
280
+ throw AppError.conflict(
281
+ `A workspace may define at most ${String(CONSENT_PURPOSES_HARD_CAP)} consent purposes`,
282
+ [{ field: 'slug', message: 'Limit reached' }],
283
+ )
284
+ }
285
+
286
+ let created: ConsentPurposeRecord
287
+ try {
288
+ created = await repository.insertPurpose(tx, {
289
+ id,
290
+ workspaceId,
291
+ slug: input.slug,
292
+ label: input.label,
293
+ description: input.description,
294
+ defaultStatus: input.defaultStatus,
295
+ sortOrder: (existing.at(-1)?.sortOrder ?? -1) + 1,
296
+ })
297
+ } catch (error: unknown) {
298
+ if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
299
+ throw duplicateSlug()
300
+ }
301
+ throw error
302
+ }
303
+
304
+ events.emit(
305
+ 'consent_purposes.purpose.created',
306
+ { type: 'consent_purpose', id: created.id },
307
+ { slug: created.slug },
308
+ )
309
+
310
+ return toView(created)
311
+ },
312
+ { workspaceId, actor: toEventActor(actor) },
313
+ )
314
+ },
315
+
316
+ async update(actor, id, changes) {
317
+ const workspaceId = requireAdminWorkspace(actor)
318
+ const existing = await require(workspaceId, id)
319
+
320
+ if (changes.label !== undefined) {
321
+ validateLabel(changes.label)
322
+ }
323
+ if (changes.description !== undefined) {
324
+ validateDescription(changes.description)
325
+ }
326
+ if (changes.defaultStatus !== undefined) {
327
+ validateDefaultStatus(changes.defaultStatus)
328
+ }
329
+
330
+ const columns: Partial<repository.ConsentPurposeColumns> = {
331
+ ...(changes.label === undefined ? {} : { label: changes.label }),
332
+ ...(changes.description === undefined ? {} : { description: changes.description }),
333
+ ...(changes.defaultStatus === undefined
334
+ ? {}
335
+ : { defaultStatus: changes.defaultStatus }),
336
+ }
337
+ const changed = changedKeys(existing, columns)
338
+ const position = changes.sortOrder
339
+
340
+ if (changed.length === 0 && position === undefined) {
341
+ return toView(existing)
342
+ }
343
+
344
+ return dependencies.transaction(
345
+ async ({ tx, events }) => {
346
+ if (position !== undefined) {
347
+ await moveToPosition(tx, workspaceId, existing, position)
348
+ }
349
+
350
+ let updated: ConsentPurposeRecord | undefined
351
+ if (changed.length > 0) {
352
+ updated = await repository.updatePurpose(tx, workspaceId, id, {
353
+ ...columns,
354
+ updatedAt: dependencies.now(),
355
+ })
356
+ if (updated === undefined) {
357
+ throw AppError.notFound('Consent purpose not found')
358
+ }
359
+ } else {
360
+ updated = await repository.findPurpose(tx, workspaceId, id)
361
+ if (updated === undefined) {
362
+ throw AppError.notFound('Consent purpose not found')
363
+ }
364
+ }
365
+
366
+ if (changed.length > 0 || position !== undefined) {
367
+ const changedPaths = [
368
+ ...changed,
369
+ ...(position !== undefined && position !== existing.sortOrder ? ['sortOrder'] : []),
370
+ ]
371
+ events.emit(
372
+ 'consent_purposes.purpose.updated',
373
+ { type: 'consent_purpose', id },
374
+ { slug: updated.slug, changed: changedPaths },
375
+ )
376
+ }
377
+
378
+ return toView(updated)
379
+ },
380
+ { workspaceId, actor: toEventActor(actor) },
381
+ )
382
+ },
383
+
384
+ async remove(actor, id) {
385
+ const workspaceId = requireAdminWorkspace(actor)
386
+ const existing = await require(workspaceId, id)
387
+
388
+ await dependencies.transaction(
389
+ async ({ tx, events }) => {
390
+ const referencing = await referencingTypes(tx, workspaceId, id)
391
+ if (referencing.length > 0) {
392
+ throw AppError.conflict(
393
+ 'Remove this purpose from every form and list that names it before deleting it',
394
+ referencing.map((type) => ({ field: type, message: 'still references this purpose' })),
395
+ )
396
+ }
397
+
398
+ try {
399
+ await repository.deletePurpose(tx, workspaceId, id)
400
+ } catch (error: unknown) {
401
+ if (postgresErrorCode(error) === FOREIGN_KEY_VIOLATION) {
402
+ throw AppError.conflict(
403
+ 'Remove this purpose from every form and list that names it before deleting it',
404
+ [{ field: 'id', message: 'still referenced' }],
405
+ )
406
+ }
407
+ throw error
408
+ }
409
+
410
+ const survivors = await repository.purposesForWorkspace(tx, workspaceId)
411
+ await renumber(tx, workspaceId, survivors)
412
+
413
+ events.emit(
414
+ 'consent_purposes.purpose.deleted',
415
+ { type: 'consent_purpose', id },
416
+ { slug: existing.slug },
417
+ )
418
+ },
419
+ { workspaceId, actor: toEventActor(actor) },
420
+ )
421
+ },
422
+ }
423
+ }
@@ -0,0 +1,32 @@
1
+ import type { ConsentPurposeStatus } from '@kelpie/schemas'
2
+
3
+ /**
4
+ * The purposes a new workspace starts with. Data, not migrations: a workspace
5
+ * owner may rename, reorder, or delete them, and add any others they need.
6
+ *
7
+ * Both starters default to `unknown` — silence about a person's wishes is not
8
+ * a grant, and every capture site (forms, lists, imports, manual override)
9
+ * writes an explicit `person_consents` row when consent is actually given.
10
+ */
11
+
12
+ export interface StarterConsentPurpose {
13
+ readonly slug: string
14
+ readonly label: string
15
+ readonly description: string
16
+ readonly defaultStatus: ConsentPurposeStatus
17
+ }
18
+
19
+ export const STARTER_CONSENT_PURPOSES: readonly StarterConsentPurpose[] = [
20
+ {
21
+ slug: 'contact',
22
+ label: 'Contact',
23
+ description: 'Being contacted by the workspace about our work together.',
24
+ defaultStatus: 'unknown',
25
+ },
26
+ {
27
+ slug: 'marketing',
28
+ label: 'Marketing',
29
+ description: 'Marketing communications — newsletters, product updates, and campaigns.',
30
+ defaultStatus: 'unknown',
31
+ },
32
+ ]
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { McpToolRegistry } from '../../runtime/module.ts'
4
+ import { idArg, listWindowShape, registerCrudTools, termArg } from '../crudTools.ts'
5
+ import {
6
+ createBody,
7
+ consentPurposeResponse,
8
+ toCreateInput,
9
+ toUpdateInput,
10
+ updateBody,
11
+ } from './routes.ts'
12
+ import type { ConsentPurposesService } from './service.ts'
13
+
14
+ /**
15
+ * `consent_purposes_*`. Same schemas and mappers as `/v1/consent_purposes`, so
16
+ * the REST surface and the MCP one cannot drift. Agents list purposes before
17
+ * a person consent write so they know which slugs the workspace defines.
18
+ */
19
+
20
+ const listArgs = z.strictObject({
21
+ ...listWindowShape,
22
+ q: termArg,
23
+ })
24
+
25
+ export function registerConsentPurposesTools(
26
+ mcp: McpToolRegistry,
27
+ service: ConsentPurposesService,
28
+ ): void {
29
+ registerCrudTools(mcp, {
30
+ resource: 'consent_purposes',
31
+ subject: 'consent purpose',
32
+ about:
33
+ 'A workspace-defined consent purpose. Read these before writing a person ' +
34
+ 'consent or setting a form/list/import purpose_id.',
35
+ service,
36
+ render: consentPurposeResponse,
37
+ listArgs,
38
+ toFilters: (args) => ({ term: args.q }),
39
+ createArgs: createBody,
40
+ toCreateInput,
41
+ updateArgs: updateBody.extend({ id: idArg }),
42
+ toUpdateInput,
43
+ })
44
+ }
@@ -6,10 +6,13 @@ import { createAgentTasksModule } from './agent-tasks/index.ts'
6
6
  import { createApiKeysModule } from './api-keys/index.ts'
7
7
  import { createAuthModule } from './auth/index.ts'
8
8
  import { createCompaniesModule } from './companies/index.ts'
9
+ import { createConsentPurposesModule } from './consent-purposes/index.ts'
10
+ import { createCustomFieldsModule } from './custom-fields/index.ts'
9
11
  import { createDashboardModule } from './dashboard/index.ts'
10
12
  import { createDealsModule } from './deals/index.ts'
11
13
  import { createDecisionsModule } from './decisions/index.ts'
12
14
  import { createEmailDomainLinkerModule } from './email-domain-linker/index.ts'
15
+ import { createEnquiriesModule } from './enquiries/index.ts'
13
16
  import { createFormsModule } from './forms/index.ts'
14
17
  import { createHandbookModule } from './handbook/index.ts'
15
18
  import { createHiringModule } from './hiring/index.ts'
@@ -47,6 +50,12 @@ export const coreModules: readonly KelpieModule[] = [
47
50
  createAuthModule(coreMigrationsDirectory),
48
51
  createWorkspaceModule(coreMigrationsDirectory),
49
52
  createApiKeysModule(coreMigrationsDirectory),
53
+ // Structural. Registers before People, Forms, Lists, and Import-Export so
54
+ // its table is defined when their fks and per-person consent join reach it.
55
+ createConsentPurposesModule(coreMigrationsDirectory),
56
+ // Structural. Registers before the six object modules so the validator
57
+ // factory it exports is present when they inject it into their services.
58
+ createCustomFieldsModule(coreMigrationsDirectory),
50
59
  createPeopleModule(coreMigrationsDirectory),
51
60
  createCompaniesModule(coreMigrationsDirectory),
52
61
  createPositionsModule(coreMigrationsDirectory),
@@ -54,6 +63,7 @@ export const coreModules: readonly KelpieModule[] = [
54
63
  createNotesModule(coreMigrationsDirectory),
55
64
  createPipelinesModule(coreMigrationsDirectory),
56
65
  createDealsModule(coreMigrationsDirectory),
66
+ createEnquiriesModule(coreMigrationsDirectory),
57
67
  createOpportunitiesModule(coreMigrationsDirectory),
58
68
  createPartnershipsModule(coreMigrationsDirectory),
59
69
  createRaisesModule(coreMigrationsDirectory),
@@ -0,0 +1,17 @@
1
+ import type { LimitCapability } from '../../runtime/entitlements.ts'
2
+
3
+ /**
4
+ * How many custom-field definitions one workspace may have across every object
5
+ * type. Open source answers unlimited; the cloud can gate it later without a
6
+ * core change.
7
+ *
8
+ * The workspace-wide count is what an entitlement caps. A per-(workspace,
9
+ * object_type) ceiling is enforced separately in the service as a hard cap that
10
+ * protects the database from a runaway create loop.
11
+ */
12
+ export const CUSTOM_FIELDS_LIMIT: LimitCapability = {
13
+ name: 'custom_fields.limit',
14
+ kind: 'limit',
15
+ description:
16
+ 'How many custom-field definitions one workspace may have across every object type. Unlimited in open source.',
17
+ }
@@ -0,0 +1,51 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /**
6
+ * Domain events published by the custom-fields module.
7
+ *
8
+ * `target` is the definition. The value-side changes ride each object module's
9
+ * own `.updated` event, with per-key entries in `changed` shaped as
10
+ * `customFields.<key>`. The webhooks bridge does not translate any of these —
11
+ * `custom_fields.field` is not in `RECORD_OBJECT_TYPES`, and there is no
12
+ * `record.*` wire event for a definition CRUD, so the four-event wire catalog
13
+ * stays unchanged.
14
+ */
15
+
16
+ export const customFieldsEvents = {
17
+ 'custom_fields.field.created': z.object({ objectType: z.string(), key: z.string() }),
18
+ 'custom_fields.field.updated': z.object({
19
+ objectType: z.string(),
20
+ key: z.string(),
21
+ changed: z.array(z.string()).readonly(),
22
+ }),
23
+ 'custom_fields.field.deleted': z.object({
24
+ objectType: z.string(),
25
+ key: z.string(),
26
+ strippedRecordCount: z.number().int(),
27
+ }),
28
+ } satisfies ModuleEventCatalog
29
+
30
+ export interface CustomFieldCreatedData {
31
+ readonly objectType: string
32
+ readonly key: string
33
+ }
34
+ export interface CustomFieldUpdatedData {
35
+ readonly objectType: string
36
+ readonly key: string
37
+ readonly changed: readonly string[]
38
+ }
39
+ export interface CustomFieldDeletedData {
40
+ readonly objectType: string
41
+ readonly key: string
42
+ readonly strippedRecordCount: number
43
+ }
44
+
45
+ declare module '../../runtime/events.ts' {
46
+ interface KelpieEventMap {
47
+ 'custom_fields.field.created': CustomFieldCreatedData
48
+ 'custom_fields.field.updated': CustomFieldUpdatedData
49
+ 'custom_fields.field.deleted': CustomFieldDeletedData
50
+ }
51
+ }
@@ -0,0 +1,61 @@
1
+ import type { KelpieModule } from '../../runtime/module.ts'
2
+ import { CUSTOM_FIELDS_LIMIT } from './capabilities.ts'
3
+ import { customFieldsEvents } from './events.ts'
4
+ import { mountCustomFieldsRoutes } from './routes.ts'
5
+ import * as schema from './schema.ts'
6
+ import { createCustomFieldDefinitionsService } from './service.ts'
7
+ import { registerCustomFieldsTools } from './tools.ts'
8
+
9
+ /**
10
+ * Custom fields: workspace-defined attributes for the six taggable record
11
+ * types. Structural because records carry values keyed by definition key, so a
12
+ * disabled module would leave the values on records with no way to read them.
13
+ *
14
+ * Requires the six object modules only for schema visibility: the strip-on-
15
+ * delete pass reads their tables through `stripKeyFromRecords`, and drizzle-kit
16
+ * needs the barrel to see them registered before this module's schema loads.
17
+ * Runtime dependency runs the other way — the six modules `requires` this one
18
+ * so the validator is present when they register.
19
+ *
20
+ * Exports the values factory so the six object modules can inject it into
21
+ * their services (`createCustomFieldValues` is the cross-module seam here).
22
+ */
23
+ export {
24
+ createCustomFieldValues,
25
+ } from './values.ts'
26
+ export type {
27
+ CustomFieldValuesValidator,
28
+ CustomFieldsMerge,
29
+ StoredCustomFieldValue,
30
+ } from './values.ts'
31
+
32
+ export function createCustomFieldsModule(migrationsDirectory: string): KelpieModule {
33
+ return {
34
+ id: 'custom-fields',
35
+ requires: ['workspace'],
36
+ structural: true,
37
+ events: customFieldsEvents,
38
+
39
+ register(context) {
40
+ context.entitlements.declare(CUSTOM_FIELDS_LIMIT)
41
+
42
+ const service = createCustomFieldDefinitionsService({
43
+ db: context.db,
44
+ transaction: context.transaction,
45
+ createId: context.createId,
46
+ now: context.now,
47
+ entitlements: context.entitlements,
48
+ })
49
+
50
+ context.schema(schema, migrationsDirectory)
51
+
52
+ context.routes((router) => {
53
+ mountCustomFieldsRoutes(router, { db: context.db, now: context.now, service })
54
+ })
55
+
56
+ registerCustomFieldsTools(context.mcp, service)
57
+
58
+ return Promise.resolve()
59
+ },
60
+ }
61
+ }