@aglyn/plugins-crm 1.0.0-beta.143

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 (669) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +57 -0
  4. package/src/index.d.ts +21 -0
  5. package/src/index.js +29 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/activity-list.d.ts +98 -0
  8. package/src/lib/components/activity-list.js +321 -0
  9. package/src/lib/components/activity-list.js.map +1 -0
  10. package/src/lib/components/activity-queries.d.ts +117 -0
  11. package/src/lib/components/activity-queries.js +198 -0
  12. package/src/lib/components/activity-queries.js.map +1 -0
  13. package/src/lib/components/add-to-list-button.d.ts +25 -0
  14. package/src/lib/components/add-to-list-button.js +64 -0
  15. package/src/lib/components/add-to-list-button.js.map +1 -0
  16. package/src/lib/components/add-to-list-dialog.d.ts +24 -0
  17. package/src/lib/components/add-to-list-dialog.js +327 -0
  18. package/src/lib/components/add-to-list-dialog.js.map +1 -0
  19. package/src/lib/components/assignment-rule-drawer.d.ts +43 -0
  20. package/src/lib/components/assignment-rule-drawer.js +293 -0
  21. package/src/lib/components/assignment-rule-drawer.js.map +1 -0
  22. package/src/lib/components/companies-bulk-bar.d.ts +29 -0
  23. package/src/lib/components/companies-bulk-bar.js +274 -0
  24. package/src/lib/components/companies-bulk-bar.js.map +1 -0
  25. package/src/lib/components/companies-section.d.ts +54 -0
  26. package/src/lib/components/companies-section.js +522 -0
  27. package/src/lib/components/companies-section.js.map +1 -0
  28. package/src/lib/components/company-contacts-card.d.ts +49 -0
  29. package/src/lib/components/company-contacts-card.js +435 -0
  30. package/src/lib/components/company-contacts-card.js.map +1 -0
  31. package/src/lib/components/company-deals-card.d.ts +20 -0
  32. package/src/lib/components/company-deals-card.js +38 -0
  33. package/src/lib/components/company-deals-card.js.map +1 -0
  34. package/src/lib/components/company-detail-page.d.ts +20 -0
  35. package/src/lib/components/company-detail-page.js +165 -0
  36. package/src/lib/components/company-detail-page.js.map +1 -0
  37. package/src/lib/components/company-edit-drawer.d.ts +65 -0
  38. package/src/lib/components/company-edit-drawer.js +433 -0
  39. package/src/lib/components/company-edit-drawer.js.map +1 -0
  40. package/src/lib/components/company-import-drawer.d.ts +42 -0
  41. package/src/lib/components/company-import-drawer.js +99 -0
  42. package/src/lib/components/company-import-drawer.js.map +1 -0
  43. package/src/lib/components/company-picker.d.ts +127 -0
  44. package/src/lib/components/company-picker.js +323 -0
  45. package/src/lib/components/company-picker.js.map +1 -0
  46. package/src/lib/components/company-properties-card.d.ts +47 -0
  47. package/src/lib/components/company-properties-card.js +289 -0
  48. package/src/lib/components/company-properties-card.js.map +1 -0
  49. package/src/lib/components/contact-address-fields.d.ts +29 -0
  50. package/src/lib/components/contact-address-fields.js +149 -0
  51. package/src/lib/components/contact-address-fields.js.map +1 -0
  52. package/src/lib/components/contact-associations-card.d.ts +72 -0
  53. package/src/lib/components/contact-associations-card.js +296 -0
  54. package/src/lib/components/contact-associations-card.js.map +1 -0
  55. package/src/lib/components/contact-custom-columns.d.ts +38 -0
  56. package/src/lib/components/contact-custom-columns.js +102 -0
  57. package/src/lib/components/contact-custom-columns.js.map +1 -0
  58. package/src/lib/components/contact-custom-fields-card.d.ts +39 -0
  59. package/src/lib/components/contact-custom-fields-card.js +204 -0
  60. package/src/lib/components/contact-custom-fields-card.js.map +1 -0
  61. package/src/lib/components/contact-deals-card.d.ts +20 -0
  62. package/src/lib/components/contact-deals-card.js +38 -0
  63. package/src/lib/components/contact-deals-card.js.map +1 -0
  64. package/src/lib/components/contact-detail-page.d.ts +46 -0
  65. package/src/lib/components/contact-detail-page.js +535 -0
  66. package/src/lib/components/contact-detail-page.js.map +1 -0
  67. package/src/lib/components/contact-duplicates-card.d.ts +42 -0
  68. package/src/lib/components/contact-duplicates-card.js +167 -0
  69. package/src/lib/components/contact-duplicates-card.js.map +1 -0
  70. package/src/lib/components/contact-field-drawer.d.ts +64 -0
  71. package/src/lib/components/contact-field-drawer.js +251 -0
  72. package/src/lib/components/contact-field-drawer.js.map +1 -0
  73. package/src/lib/components/contact-import-drawer.d.ts +46 -0
  74. package/src/lib/components/contact-import-drawer.js +149 -0
  75. package/src/lib/components/contact-import-drawer.js.map +1 -0
  76. package/src/lib/components/contact-known-by-card.d.ts +39 -0
  77. package/src/lib/components/contact-known-by-card.js +142 -0
  78. package/src/lib/components/contact-known-by-card.js.map +1 -0
  79. package/src/lib/components/contact-list-columns.d.ts +53 -0
  80. package/src/lib/components/contact-list-columns.js +288 -0
  81. package/src/lib/components/contact-list-columns.js.map +1 -0
  82. package/src/lib/components/contact-merge-dialog.d.ts +79 -0
  83. package/src/lib/components/contact-merge-dialog.js +405 -0
  84. package/src/lib/components/contact-merge-dialog.js.map +1 -0
  85. package/src/lib/components/contact-properties-card.d.ts +89 -0
  86. package/src/lib/components/contact-properties-card.js +492 -0
  87. package/src/lib/components/contact-properties-card.js.map +1 -0
  88. package/src/lib/components/contact-timeline-card.d.ts +68 -0
  89. package/src/lib/components/contact-timeline-card.js +435 -0
  90. package/src/lib/components/contact-timeline-card.js.map +1 -0
  91. package/src/lib/components/contacts-bulk-bar.d.ts +91 -0
  92. package/src/lib/components/contacts-bulk-bar.js +493 -0
  93. package/src/lib/components/contacts-bulk-bar.js.map +1 -0
  94. package/src/lib/components/contacts-section.d.ts +26 -0
  95. package/src/lib/components/contacts-section.js +1025 -0
  96. package/src/lib/components/contacts-section.js.map +1 -0
  97. package/src/lib/components/copy-capture-address-button.d.ts +33 -0
  98. package/src/lib/components/copy-capture-address-button.js +60 -0
  99. package/src/lib/components/copy-capture-address-button.js.map +1 -0
  100. package/src/lib/components/crm-attribution-zone.d.ts +38 -0
  101. package/src/lib/components/crm-attribution-zone.js +36 -0
  102. package/src/lib/components/crm-attribution-zone.js.map +1 -0
  103. package/src/lib/components/crm-booking-zone.d.ts +61 -0
  104. package/src/lib/components/crm-booking-zone.js +50 -0
  105. package/src/lib/components/crm-booking-zone.js.map +1 -0
  106. package/src/lib/components/crm-bulk-bar-frame.d.ts +47 -0
  107. package/src/lib/components/crm-bulk-bar-frame.js +137 -0
  108. package/src/lib/components/crm-bulk-bar-frame.js.map +1 -0
  109. package/src/lib/components/crm-call-actions.d.ts +65 -0
  110. package/src/lib/components/crm-call-actions.js +110 -0
  111. package/src/lib/components/crm-call-actions.js.map +1 -0
  112. package/src/lib/components/crm-column-menu.d.ts +21 -0
  113. package/src/lib/components/crm-column-menu.js +103 -0
  114. package/src/lib/components/crm-column-menu.js.map +1 -0
  115. package/src/lib/components/crm-console-page.d.ts +19 -0
  116. package/src/lib/components/crm-console-page.js +151 -0
  117. package/src/lib/components/crm-console-page.js.map +1 -0
  118. package/src/lib/components/crm-console-sections.d.ts +52 -0
  119. package/src/lib/components/crm-console-sections.js +83 -0
  120. package/src/lib/components/crm-console-sections.js.map +1 -0
  121. package/src/lib/components/crm-custom-field-control.d.ts +26 -0
  122. package/src/lib/components/crm-custom-field-control.js +131 -0
  123. package/src/lib/components/crm-custom-field-control.js.map +1 -0
  124. package/src/lib/components/crm-email-template-tools.d.ts +69 -0
  125. package/src/lib/components/crm-email-template-tools.js +240 -0
  126. package/src/lib/components/crm-email-template-tools.js.map +1 -0
  127. package/src/lib/components/crm-export-all-button.d.ts +39 -0
  128. package/src/lib/components/crm-export-all-button.js +98 -0
  129. package/src/lib/components/crm-export-all-button.js.map +1 -0
  130. package/src/lib/components/crm-filter-bar.d.ts +53 -0
  131. package/src/lib/components/crm-filter-bar.js +294 -0
  132. package/src/lib/components/crm-filter-bar.js.map +1 -0
  133. package/src/lib/components/crm-glance-card.d.ts +54 -0
  134. package/src/lib/components/crm-glance-card.js +219 -0
  135. package/src/lib/components/crm-glance-card.js.map +1 -0
  136. package/src/lib/components/crm-next-activity-column.d.ts +35 -0
  137. package/src/lib/components/crm-next-activity-column.js +100 -0
  138. package/src/lib/components/crm-next-activity-column.js.map +1 -0
  139. package/src/lib/components/crm-record-header.d.ts +97 -0
  140. package/src/lib/components/crm-record-header.js +160 -0
  141. package/src/lib/components/crm-record-header.js.map +1 -0
  142. package/src/lib/components/crm-record-insights-zone.d.ts +50 -0
  143. package/src/lib/components/crm-record-insights-zone.js +169 -0
  144. package/src/lib/components/crm-record-insights-zone.js.map +1 -0
  145. package/src/lib/components/crm-record-picker.d.ts +42 -0
  146. package/src/lib/components/crm-record-picker.js +104 -0
  147. package/src/lib/components/crm-record-picker.js.map +1 -0
  148. package/src/lib/components/crm-send-email-button.d.ts +39 -0
  149. package/src/lib/components/crm-send-email-button.js +81 -0
  150. package/src/lib/components/crm-send-email-button.js.map +1 -0
  151. package/src/lib/components/crm-send-email-dialog.d.ts +61 -0
  152. package/src/lib/components/crm-send-email-dialog.js +851 -0
  153. package/src/lib/components/crm-send-email-dialog.js.map +1 -0
  154. package/src/lib/components/crm-site-picker.d.ts +61 -0
  155. package/src/lib/components/crm-site-picker.js +99 -0
  156. package/src/lib/components/crm-site-picker.js.map +1 -0
  157. package/src/lib/components/crm-suite-lock.d.ts +29 -0
  158. package/src/lib/components/crm-suite-lock.js +114 -0
  159. package/src/lib/components/crm-suite-lock.js.map +1 -0
  160. package/src/lib/components/crm-tasks-due-card.d.ts +42 -0
  161. package/src/lib/components/crm-tasks-due-card.js +225 -0
  162. package/src/lib/components/crm-tasks-due-card.js.map +1 -0
  163. package/src/lib/components/crm-views-control.d.ts +65 -0
  164. package/src/lib/components/crm-views-control.js +518 -0
  165. package/src/lib/components/crm-views-control.js.map +1 -0
  166. package/src/lib/components/csv-import-drawer.d.ts +132 -0
  167. package/src/lib/components/csv-import-drawer.js +746 -0
  168. package/src/lib/components/csv-import-drawer.js.map +1 -0
  169. package/src/lib/components/deal-board.d.ts +70 -0
  170. package/src/lib/components/deal-board.js +478 -0
  171. package/src/lib/components/deal-board.js.map +1 -0
  172. package/src/lib/components/deal-detail-page.d.ts +18 -0
  173. package/src/lib/components/deal-detail-page.js +323 -0
  174. package/src/lib/components/deal-detail-page.js.map +1 -0
  175. package/src/lib/components/deal-edit-drawer.d.ts +59 -0
  176. package/src/lib/components/deal-edit-drawer.js +640 -0
  177. package/src/lib/components/deal-edit-drawer.js.map +1 -0
  178. package/src/lib/components/deal-import-drawer.d.ts +24 -0
  179. package/src/lib/components/deal-import-drawer.js +83 -0
  180. package/src/lib/components/deal-import-drawer.js.map +1 -0
  181. package/src/lib/components/deal-products-card.d.ts +48 -0
  182. package/src/lib/components/deal-products-card.js +614 -0
  183. package/src/lib/components/deal-products-card.js.map +1 -0
  184. package/src/lib/components/deal-properties-card.d.ts +29 -0
  185. package/src/lib/components/deal-properties-card.js +144 -0
  186. package/src/lib/components/deal-properties-card.js.map +1 -0
  187. package/src/lib/components/deal-stage-card.d.ts +24 -0
  188. package/src/lib/components/deal-stage-card.js +199 -0
  189. package/src/lib/components/deal-stage-card.js.map +1 -0
  190. package/src/lib/components/deals-bulk-bar.d.ts +31 -0
  191. package/src/lib/components/deals-bulk-bar.js +340 -0
  192. package/src/lib/components/deals-bulk-bar.js.map +1 -0
  193. package/src/lib/components/deals-section.d.ts +49 -0
  194. package/src/lib/components/deals-section.js +767 -0
  195. package/src/lib/components/deals-section.js.map +1 -0
  196. package/src/lib/components/email-capture-card.d.ts +42 -0
  197. package/src/lib/components/email-capture-card.js +134 -0
  198. package/src/lib/components/email-capture-card.js.map +1 -0
  199. package/src/lib/components/email-template-drawer.d.ts +33 -0
  200. package/src/lib/components/email-template-drawer.js +209 -0
  201. package/src/lib/components/email-template-drawer.js.map +1 -0
  202. package/src/lib/components/email-templates-card.d.ts +33 -0
  203. package/src/lib/components/email-templates-card.js +370 -0
  204. package/src/lib/components/email-templates-card.js.map +1 -0
  205. package/src/lib/components/erase-person-action.d.ts +92 -0
  206. package/src/lib/components/erase-person-action.js +261 -0
  207. package/src/lib/components/erase-person-action.js.map +1 -0
  208. package/src/lib/components/fields-section.d.ts +37 -0
  209. package/src/lib/components/fields-section.js +641 -0
  210. package/src/lib/components/fields-section.js.map +1 -0
  211. package/src/lib/components/form-contact-fields-card.d.ts +46 -0
  212. package/src/lib/components/form-contact-fields-card.js +253 -0
  213. package/src/lib/components/form-contact-fields-card.js.map +1 -0
  214. package/src/lib/components/insert-link-at-caret.d.ts +28 -0
  215. package/src/lib/components/insert-link-at-caret.js +37 -0
  216. package/src/lib/components/insert-link-at-caret.js.map +1 -0
  217. package/src/lib/components/lead-convert-dialog.d.ts +32 -0
  218. package/src/lib/components/lead-convert-dialog.js +493 -0
  219. package/src/lib/components/lead-convert-dialog.js.map +1 -0
  220. package/src/lib/components/lead-detail-page.d.ts +16 -0
  221. package/src/lib/components/lead-detail-page.js +163 -0
  222. package/src/lib/components/lead-detail-page.js.map +1 -0
  223. package/src/lib/components/lead-history-card.d.ts +32 -0
  224. package/src/lib/components/lead-history-card.js +165 -0
  225. package/src/lib/components/lead-history-card.js.map +1 -0
  226. package/src/lib/components/lead-import-drawer.d.ts +24 -0
  227. package/src/lib/components/lead-import-drawer.js +95 -0
  228. package/src/lib/components/lead-import-drawer.js.map +1 -0
  229. package/src/lib/components/lead-owner-select.d.ts +35 -0
  230. package/src/lib/components/lead-owner-select.js +91 -0
  231. package/src/lib/components/lead-owner-select.js.map +1 -0
  232. package/src/lib/components/lead-properties-card.d.ts +61 -0
  233. package/src/lib/components/lead-properties-card.js +395 -0
  234. package/src/lib/components/lead-properties-card.js.map +1 -0
  235. package/src/lib/components/lead-status-chip.d.ts +12 -0
  236. package/src/lib/components/lead-status-chip.js +43 -0
  237. package/src/lib/components/lead-status-chip.js.map +1 -0
  238. package/src/lib/components/lead-surfaces-note.d.ts +126 -0
  239. package/src/lib/components/lead-surfaces-note.js +262 -0
  240. package/src/lib/components/lead-surfaces-note.js.map +1 -0
  241. package/src/lib/components/lead-unqualify-dialog.d.ts +24 -0
  242. package/src/lib/components/lead-unqualify-dialog.js +125 -0
  243. package/src/lib/components/lead-unqualify-dialog.js.map +1 -0
  244. package/src/lib/components/leads-bulk-bar.d.ts +58 -0
  245. package/src/lib/components/leads-bulk-bar.js +307 -0
  246. package/src/lib/components/leads-bulk-bar.js.map +1 -0
  247. package/src/lib/components/leads-section.d.ts +23 -0
  248. package/src/lib/components/leads-section.js +664 -0
  249. package/src/lib/components/leads-section.js.map +1 -0
  250. package/src/lib/components/linked-deals-card.d.ts +32 -0
  251. package/src/lib/components/linked-deals-card.js +163 -0
  252. package/src/lib/components/linked-deals-card.js.map +1 -0
  253. package/src/lib/components/log-activity-dialog.d.ts +60 -0
  254. package/src/lib/components/log-activity-dialog.js +368 -0
  255. package/src/lib/components/log-activity-dialog.js.map +1 -0
  256. package/src/lib/components/lost-reason-dialog.d.ts +26 -0
  257. package/src/lib/components/lost-reason-dialog.js +95 -0
  258. package/src/lib/components/lost-reason-dialog.js.map +1 -0
  259. package/src/lib/components/new-contact-drawer.d.ts +78 -0
  260. package/src/lib/components/new-contact-drawer.js +343 -0
  261. package/src/lib/components/new-contact-drawer.js.map +1 -0
  262. package/src/lib/components/org-lead-surfaces-note.d.ts +57 -0
  263. package/src/lib/components/org-lead-surfaces-note.js +172 -0
  264. package/src/lib/components/org-lead-surfaces-note.js.map +1 -0
  265. package/src/lib/components/owner-avatar.d.ts +18 -0
  266. package/src/lib/components/owner-avatar.js +61 -0
  267. package/src/lib/components/owner-avatar.js.map +1 -0
  268. package/src/lib/components/pipeline-stages-dialog.d.ts +43 -0
  269. package/src/lib/components/pipeline-stages-dialog.js +339 -0
  270. package/src/lib/components/pipeline-stages-dialog.js.map +1 -0
  271. package/src/lib/components/pipelines-dialog.d.ts +55 -0
  272. package/src/lib/components/pipelines-dialog.js +517 -0
  273. package/src/lib/components/pipelines-dialog.js.map +1 -0
  274. package/src/lib/components/recent-activity-feed.d.ts +39 -0
  275. package/src/lib/components/recent-activity-feed.js +103 -0
  276. package/src/lib/components/recent-activity-feed.js.map +1 -0
  277. package/src/lib/components/recipes-card.d.ts +39 -0
  278. package/src/lib/components/recipes-card.js +485 -0
  279. package/src/lib/components/recipes-card.js.map +1 -0
  280. package/src/lib/components/record-activity-card.d.ts +26 -0
  281. package/src/lib/components/record-activity-card.js +121 -0
  282. package/src/lib/components/record-activity-card.js.map +1 -0
  283. package/src/lib/components/record-files-card.d.ts +67 -0
  284. package/src/lib/components/record-files-card.js +290 -0
  285. package/src/lib/components/record-files-card.js.map +1 -0
  286. package/src/lib/components/record-tasks-card.d.ts +32 -0
  287. package/src/lib/components/record-tasks-card.js +306 -0
  288. package/src/lib/components/record-tasks-card.js.map +1 -0
  289. package/src/lib/components/reports/activity-card.d.ts +57 -0
  290. package/src/lib/components/reports/activity-card.js +281 -0
  291. package/src/lib/components/reports/activity-card.js.map +1 -0
  292. package/src/lib/components/reports/closed-deals-card.d.ts +20 -0
  293. package/src/lib/components/reports/closed-deals-card.js +194 -0
  294. package/src/lib/components/reports/closed-deals-card.js.map +1 -0
  295. package/src/lib/components/reports/contacts-mix-card.d.ts +27 -0
  296. package/src/lib/components/reports/contacts-mix-card.js +161 -0
  297. package/src/lib/components/reports/contacts-mix-card.js.map +1 -0
  298. package/src/lib/components/reports/contacts-trend-card.d.ts +31 -0
  299. package/src/lib/components/reports/contacts-trend-card.js +144 -0
  300. package/src/lib/components/reports/contacts-trend-card.js.map +1 -0
  301. package/src/lib/components/reports/forecast-card.d.ts +22 -0
  302. package/src/lib/components/reports/forecast-card.js +251 -0
  303. package/src/lib/components/reports/forecast-card.js.map +1 -0
  304. package/src/lib/components/reports/lead-counts.d.ts +32 -0
  305. package/src/lib/components/reports/lead-counts.js +44 -0
  306. package/src/lib/components/reports/lead-counts.js.map +1 -0
  307. package/src/lib/components/reports/lead-funnel-card.d.ts +38 -0
  308. package/src/lib/components/reports/lead-funnel-card.js +375 -0
  309. package/src/lib/components/reports/lead-funnel-card.js.map +1 -0
  310. package/src/lib/components/reports/pipeline-card.d.ts +19 -0
  311. package/src/lib/components/reports/pipeline-card.js +338 -0
  312. package/src/lib/components/reports/pipeline-card.js.map +1 -0
  313. package/src/lib/components/reports/report-bar-chart.d.ts +39 -0
  314. package/src/lib/components/reports/report-bar-chart.js +133 -0
  315. package/src/lib/components/reports/report-bar-chart.js.map +1 -0
  316. package/src/lib/components/reports/report-breakdown.d.ts +32 -0
  317. package/src/lib/components/reports/report-breakdown.js +105 -0
  318. package/src/lib/components/reports/report-breakdown.js.map +1 -0
  319. package/src/lib/components/reports/report-export.d.ts +37 -0
  320. package/src/lib/components/reports/report-export.js +66 -0
  321. package/src/lib/components/reports/report-export.js.map +1 -0
  322. package/src/lib/components/reports/report-format.d.ts +36 -0
  323. package/src/lib/components/reports/report-format.js +43 -0
  324. package/src/lib/components/reports/report-format.js.map +1 -0
  325. package/src/lib/components/reports/report-scope.d.ts +81 -0
  326. package/src/lib/components/reports/report-scope.js +58 -0
  327. package/src/lib/components/reports/report-scope.js.map +1 -0
  328. package/src/lib/components/reports/report-stat-tile.d.ts +47 -0
  329. package/src/lib/components/reports/report-stat-tile.js +96 -0
  330. package/src/lib/components/reports/report-stat-tile.js.map +1 -0
  331. package/src/lib/components/reports/source-conversion-card.d.ts +28 -0
  332. package/src/lib/components/reports/source-conversion-card.js +205 -0
  333. package/src/lib/components/reports/source-conversion-card.js.map +1 -0
  334. package/src/lib/components/reports/tasks-card.d.ts +26 -0
  335. package/src/lib/components/reports/tasks-card.js +279 -0
  336. package/src/lib/components/reports/tasks-card.js.map +1 -0
  337. package/src/lib/components/reports/use-aggregate-read.d.ts +99 -0
  338. package/src/lib/components/reports/use-aggregate-read.js +195 -0
  339. package/src/lib/components/reports/use-aggregate-read.js.map +1 -0
  340. package/src/lib/components/reports/won-lost-by-owner-card.d.ts +30 -0
  341. package/src/lib/components/reports/won-lost-by-owner-card.js +168 -0
  342. package/src/lib/components/reports/won-lost-by-owner-card.js.map +1 -0
  343. package/src/lib/components/reports-section.d.ts +42 -0
  344. package/src/lib/components/reports-section.js +308 -0
  345. package/src/lib/components/reports-section.js.map +1 -0
  346. package/src/lib/components/sending-addresses-card.d.ts +49 -0
  347. package/src/lib/components/sending-addresses-card.js +262 -0
  348. package/src/lib/components/sending-addresses-card.js.map +1 -0
  349. package/src/lib/components/settings-section.d.ts +151 -0
  350. package/src/lib/components/settings-section.js +783 -0
  351. package/src/lib/components/settings-section.js.map +1 -0
  352. package/src/lib/components/task-cells.d.ts +51 -0
  353. package/src/lib/components/task-cells.js +139 -0
  354. package/src/lib/components/task-cells.js.map +1 -0
  355. package/src/lib/components/task-edit-drawer.d.ts +53 -0
  356. package/src/lib/components/task-edit-drawer.js +483 -0
  357. package/src/lib/components/task-edit-drawer.js.map +1 -0
  358. package/src/lib/components/task-import-drawer.d.ts +24 -0
  359. package/src/lib/components/task-import-drawer.js +82 -0
  360. package/src/lib/components/task-import-drawer.js.map +1 -0
  361. package/src/lib/components/task-snooze-menu.d.ts +65 -0
  362. package/src/lib/components/task-snooze-menu.js +207 -0
  363. package/src/lib/components/task-snooze-menu.js.map +1 -0
  364. package/src/lib/components/tasks-bulk-bar.d.ts +25 -0
  365. package/src/lib/components/tasks-bulk-bar.js +348 -0
  366. package/src/lib/components/tasks-bulk-bar.js.map +1 -0
  367. package/src/lib/components/tasks-calendar.d.ts +38 -0
  368. package/src/lib/components/tasks-calendar.js +228 -0
  369. package/src/lib/components/tasks-calendar.js.map +1 -0
  370. package/src/lib/components/tasks-section.d.ts +27 -0
  371. package/src/lib/components/tasks-section.js +579 -0
  372. package/src/lib/components/tasks-section.js.map +1 -0
  373. package/src/lib/components/use-contact-campaign-emails.d.ts +32 -0
  374. package/src/lib/components/use-contact-campaign-emails.js +83 -0
  375. package/src/lib/components/use-contact-campaign-emails.js.map +1 -0
  376. package/src/lib/components/use-crm-api.d.ts +44 -0
  377. package/src/lib/components/use-crm-api.js +84 -0
  378. package/src/lib/components/use-crm-api.js.map +1 -0
  379. package/src/lib/components/use-crm-inbound-address.d.ts +60 -0
  380. package/src/lib/components/use-crm-inbound-address.js +124 -0
  381. package/src/lib/components/use-crm-inbound-address.js.map +1 -0
  382. package/src/lib/components/use-emails-hub-path.d.ts +24 -0
  383. package/src/lib/components/use-emails-hub-path.js +59 -0
  384. package/src/lib/components/use-emails-hub-path.js.map +1 -0
  385. package/src/lib/components/use-member-email-aliases.d.ts +54 -0
  386. package/src/lib/components/use-member-email-aliases.js +186 -0
  387. package/src/lib/components/use-member-email-aliases.js.map +1 -0
  388. package/src/lib/components/use-org-members.d.ts +40 -0
  389. package/src/lib/components/use-org-members.js +100 -0
  390. package/src/lib/components/use-org-members.js.map +1 -0
  391. package/src/lib/constants/api-routes.d.ts +109 -0
  392. package/src/lib/constants/api-routes.js +74 -0
  393. package/src/lib/constants/api-routes.js.map +1 -0
  394. package/src/lib/constants/bundle-common.d.ts +14 -0
  395. package/src/lib/constants/bundle-common.js +14 -0
  396. package/src/lib/constants/bundle-common.js.map +1 -0
  397. package/src/lib/constants/company-filters.d.ts +18 -0
  398. package/src/lib/constants/company-filters.js +51 -0
  399. package/src/lib/constants/company-filters.js.map +1 -0
  400. package/src/lib/constants/contact-filters.d.ts +38 -0
  401. package/src/lib/constants/contact-filters.js +294 -0
  402. package/src/lib/constants/contact-filters.js.map +1 -0
  403. package/src/lib/hooks/use-contact-field-definitions.d.ts +48 -0
  404. package/src/lib/hooks/use-contact-field-definitions.js +72 -0
  405. package/src/lib/hooks/use-contact-field-definitions.js.map +1 -0
  406. package/src/lib/hooks/use-contact-update.d.ts +25 -0
  407. package/src/lib/hooks/use-contact-update.js +80 -0
  408. package/src/lib/hooks/use-contact-update.js.map +1 -0
  409. package/src/lib/hooks/use-crm-activity-logger.d.ts +73 -0
  410. package/src/lib/hooks/use-crm-activity-logger.js +101 -0
  411. package/src/lib/hooks/use-crm-activity-logger.js.map +1 -0
  412. package/src/lib/hooks/use-crm-bulk-apply.d.ts +52 -0
  413. package/src/lib/hooks/use-crm-bulk-apply.js +112 -0
  414. package/src/lib/hooks/use-crm-bulk-apply.js.map +1 -0
  415. package/src/lib/hooks/use-crm-default-view.d.ts +24 -0
  416. package/src/lib/hooks/use-crm-default-view.js +64 -0
  417. package/src/lib/hooks/use-crm-default-view.js.map +1 -0
  418. package/src/lib/hooks/use-crm-email-templates.d.ts +59 -0
  419. package/src/lib/hooks/use-crm-email-templates.js +103 -0
  420. package/src/lib/hooks/use-crm-email-templates.js.map +1 -0
  421. package/src/lib/hooks/use-crm-hub-path.d.ts +29 -0
  422. package/src/lib/hooks/use-crm-hub-path.js +41 -0
  423. package/src/lib/hooks/use-crm-hub-path.js.map +1 -0
  424. package/src/lib/hooks/use-crm-org-mount.d.ts +97 -0
  425. package/src/lib/hooks/use-crm-org-mount.js +215 -0
  426. package/src/lib/hooks/use-crm-org-mount.js.map +1 -0
  427. package/src/lib/hooks/use-crm-record-names.d.ts +52 -0
  428. package/src/lib/hooks/use-crm-record-names.js +126 -0
  429. package/src/lib/hooks/use-crm-record-names.js.map +1 -0
  430. package/src/lib/hooks/use-crm-records-quota.d.ts +68 -0
  431. package/src/lib/hooks/use-crm-records-quota.js +118 -0
  432. package/src/lib/hooks/use-crm-records-quota.js.map +1 -0
  433. package/src/lib/hooks/use-crm-saved-view.d.ts +96 -0
  434. package/src/lib/hooks/use-crm-saved-view.js +329 -0
  435. package/src/lib/hooks/use-crm-saved-view.js.map +1 -0
  436. package/src/lib/hooks/use-crm-scope.d.ts +117 -0
  437. package/src/lib/hooks/use-crm-scope.js +147 -0
  438. package/src/lib/hooks/use-crm-scope.js.map +1 -0
  439. package/src/lib/hooks/use-crm-tasks.d.ts +85 -0
  440. package/src/lib/hooks/use-crm-tasks.js +153 -0
  441. package/src/lib/hooks/use-crm-tasks.js.map +1 -0
  442. package/src/lib/hooks/use-crm-view-grid.d.ts +55 -0
  443. package/src/lib/hooks/use-crm-view-grid.js +170 -0
  444. package/src/lib/hooks/use-crm-view-grid.js.map +1 -0
  445. package/src/lib/hooks/use-crm-views.d.ts +42 -0
  446. package/src/lib/hooks/use-crm-views.js +84 -0
  447. package/src/lib/hooks/use-crm-views.js.map +1 -0
  448. package/src/lib/hooks/use-deal-stage-api.d.ts +69 -0
  449. package/src/lib/hooks/use-deal-stage-api.js +78 -0
  450. package/src/lib/hooks/use-deal-stage-api.js.map +1 -0
  451. package/src/lib/hooks/use-deals.d.ts +47 -0
  452. package/src/lib/hooks/use-deals.js +105 -0
  453. package/src/lib/hooks/use-deals.js.map +1 -0
  454. package/src/lib/hooks/use-org-leads.d.ts +53 -0
  455. package/src/lib/hooks/use-org-leads.js +114 -0
  456. package/src/lib/hooks/use-org-leads.js.map +1 -0
  457. package/src/lib/hooks/use-org-member-directory.d.ts +36 -0
  458. package/src/lib/hooks/use-org-member-directory.js +116 -0
  459. package/src/lib/hooks/use-org-member-directory.js.map +1 -0
  460. package/src/lib/hooks/use-org-member-options.d.ts +38 -0
  461. package/src/lib/hooks/use-org-member-options.js +131 -0
  462. package/src/lib/hooks/use-org-member-options.js.map +1 -0
  463. package/src/lib/hooks/use-pipeline.d.ts +71 -0
  464. package/src/lib/hooks/use-pipeline.js +159 -0
  465. package/src/lib/hooks/use-pipeline.js.map +1 -0
  466. package/src/lib/model/companies-bulk-writes.d.ts +40 -0
  467. package/src/lib/model/companies-bulk-writes.js +103 -0
  468. package/src/lib/model/companies-bulk-writes.js.map +1 -0
  469. package/src/lib/model/companies-csv.d.ts +36 -0
  470. package/src/lib/model/companies-csv.js +38 -0
  471. package/src/lib/model/companies-csv.js.map +1 -0
  472. package/src/lib/model/companies.d.ts +99 -0
  473. package/src/lib/model/companies.js +168 -0
  474. package/src/lib/model/companies.js.map +1 -0
  475. package/src/lib/model/company-delete-route.d.ts +43 -0
  476. package/src/lib/model/company-delete-route.js +31 -0
  477. package/src/lib/model/company-delete-route.js.map +1 -0
  478. package/src/lib/model/company-delete.d.ts +42 -0
  479. package/src/lib/model/company-delete.js +52 -0
  480. package/src/lib/model/company-delete.js.map +1 -0
  481. package/src/lib/model/contact-duplicates.d.ts +58 -0
  482. package/src/lib/model/contact-duplicates.js +67 -0
  483. package/src/lib/model/contact-duplicates.js.map +1 -0
  484. package/src/lib/model/contact-record.d.ts +113 -0
  485. package/src/lib/model/contact-record.js +70 -0
  486. package/src/lib/model/contact-record.js.map +1 -0
  487. package/src/lib/model/contact-update.d.ts +93 -0
  488. package/src/lib/model/contact-update.js +50 -0
  489. package/src/lib/model/contact-update.js.map +1 -0
  490. package/src/lib/model/contacts-bulk-writes.d.ts +173 -0
  491. package/src/lib/model/contacts-bulk-writes.js +196 -0
  492. package/src/lib/model/contacts-bulk-writes.js.map +1 -0
  493. package/src/lib/model/contacts-csv.d.ts +54 -0
  494. package/src/lib/model/contacts-csv.js +67 -0
  495. package/src/lib/model/contacts-csv.js.map +1 -0
  496. package/src/lib/model/contacts-list-seed.d.ts +51 -0
  497. package/src/lib/model/contacts-list-seed.js +63 -0
  498. package/src/lib/model/contacts-list-seed.js.map +1 -0
  499. package/src/lib/model/crm-activity-report.d.ts +27 -0
  500. package/src/lib/model/crm-activity-report.js +56 -0
  501. package/src/lib/model/crm-activity-report.js.map +1 -0
  502. package/src/lib/model/crm-api.d.ts +49 -0
  503. package/src/lib/model/crm-api.js +47 -0
  504. package/src/lib/model/crm-api.js.map +1 -0
  505. package/src/lib/model/crm-bulk-writes.d.ts +147 -0
  506. package/src/lib/model/crm-bulk-writes.js +207 -0
  507. package/src/lib/model/crm-bulk-writes.js.map +1 -0
  508. package/src/lib/model/crm-company-import.d.ts +154 -0
  509. package/src/lib/model/crm-company-import.js +331 -0
  510. package/src/lib/model/crm-company-import.js.map +1 -0
  511. package/src/lib/model/crm-custom-draft.d.ts +62 -0
  512. package/src/lib/model/crm-custom-draft.js +67 -0
  513. package/src/lib/model/crm-custom-draft.js.map +1 -0
  514. package/src/lib/model/crm-deal-import.d.ts +112 -0
  515. package/src/lib/model/crm-deal-import.js +263 -0
  516. package/src/lib/model/crm-deal-import.js.map +1 -0
  517. package/src/lib/model/crm-import.d.ts +244 -0
  518. package/src/lib/model/crm-import.js +466 -0
  519. package/src/lib/model/crm-import.js.map +1 -0
  520. package/src/lib/model/crm-lead-import.d.ts +105 -0
  521. package/src/lib/model/crm-lead-import.js +255 -0
  522. package/src/lib/model/crm-lead-import.js.map +1 -0
  523. package/src/lib/model/crm-record-routes.d.ts +21 -0
  524. package/src/lib/model/crm-record-routes.js +70 -0
  525. package/src/lib/model/crm-record-routes.js.map +1 -0
  526. package/src/lib/model/crm-routes.d.ts +101 -0
  527. package/src/lib/model/crm-routes.js +92 -0
  528. package/src/lib/model/crm-routes.js.map +1 -0
  529. package/src/lib/model/crm-task-import.d.ts +94 -0
  530. package/src/lib/model/crm-task-import.js +275 -0
  531. package/src/lib/model/crm-task-import.js.map +1 -0
  532. package/src/lib/model/crm-view-param.d.ts +43 -0
  533. package/src/lib/model/crm-view-param.js +49 -0
  534. package/src/lib/model/crm-view-param.js.map +1 -0
  535. package/src/lib/model/deal-board-model.d.ts +241 -0
  536. package/src/lib/model/deal-board-model.js +439 -0
  537. package/src/lib/model/deal-board-model.js.map +1 -0
  538. package/src/lib/model/deal-form-model.d.ts +114 -0
  539. package/src/lib/model/deal-form-model.js +218 -0
  540. package/src/lib/model/deal-form-model.js.map +1 -0
  541. package/src/lib/model/deals-csv.d.ts +32 -0
  542. package/src/lib/model/deals-csv.js +37 -0
  543. package/src/lib/model/deals-csv.js.map +1 -0
  544. package/src/lib/model/import-column-shapes.d.ts +36 -0
  545. package/src/lib/model/import-column-shapes.js +76 -0
  546. package/src/lib/model/import-column-shapes.js.map +1 -0
  547. package/src/lib/model/lead-company-suggestion.d.ts +61 -0
  548. package/src/lib/model/lead-company-suggestion.js +65 -0
  549. package/src/lib/model/lead-company-suggestion.js.map +1 -0
  550. package/src/lib/model/lead-filters.d.ts +29 -0
  551. package/src/lib/model/lead-filters.js +39 -0
  552. package/src/lib/model/lead-filters.js.map +1 -0
  553. package/src/lib/model/lead-surfaces.d.ts +58 -0
  554. package/src/lib/model/lead-surfaces.js +67 -0
  555. package/src/lib/model/lead-surfaces.js.map +1 -0
  556. package/src/lib/model/leads-csv.d.ts +40 -0
  557. package/src/lib/model/leads-csv.js +40 -0
  558. package/src/lib/model/leads-csv.js.map +1 -0
  559. package/src/lib/model/next-activity-api.d.ts +31 -0
  560. package/src/lib/model/next-activity-api.js +57 -0
  561. package/src/lib/model/next-activity-api.js.map +1 -0
  562. package/src/lib/model/next-activity.d.ts +64 -0
  563. package/src/lib/model/next-activity.js +47 -0
  564. package/src/lib/model/next-activity.js.map +1 -0
  565. package/src/lib/model/person-key-web.d.ts +43 -0
  566. package/src/lib/model/person-key-web.js +52 -0
  567. package/src/lib/model/person-key-web.js.map +1 -0
  568. package/src/lib/model/record-facts.d.ts +282 -0
  569. package/src/lib/model/record-facts.js +434 -0
  570. package/src/lib/model/record-facts.js.map +1 -0
  571. package/src/lib/model/task-api.d.ts +28 -0
  572. package/src/lib/model/task-api.js +57 -0
  573. package/src/lib/model/task-api.js.map +1 -0
  574. package/src/lib/model/task-calendar.d.ts +108 -0
  575. package/src/lib/model/task-calendar.js +139 -0
  576. package/src/lib/model/task-calendar.js.map +1 -0
  577. package/src/lib/model/task-routes.d.ts +177 -0
  578. package/src/lib/model/task-routes.js +197 -0
  579. package/src/lib/model/task-routes.js.map +1 -0
  580. package/src/lib/model/task-scope.d.ts +45 -0
  581. package/src/lib/model/task-scope.js +51 -0
  582. package/src/lib/model/task-scope.js.map +1 -0
  583. package/src/lib/model/task-views.d.ts +149 -0
  584. package/src/lib/model/task-views.js +286 -0
  585. package/src/lib/model/task-views.js.map +1 -0
  586. package/src/lib/model/tasks-csv.d.ts +28 -0
  587. package/src/lib/model/tasks-csv.js +28 -0
  588. package/src/lib/model/tasks-csv.js.map +1 -0
  589. package/src/lib/plugin.d.ts +32 -0
  590. package/src/lib/plugin.js +208 -0
  591. package/src/lib/plugin.js.map +1 -0
  592. package/src/lib/server/companies-import.d.ts +57 -0
  593. package/src/lib/server/companies-import.js +242 -0
  594. package/src/lib/server/companies-import.js.map +1 -0
  595. package/src/lib/server/company-delete.d.ts +59 -0
  596. package/src/lib/server/company-delete.js +146 -0
  597. package/src/lib/server/company-delete.js.map +1 -0
  598. package/src/lib/server/contact-email-history.d.ts +82 -0
  599. package/src/lib/server/contact-email-history.js +264 -0
  600. package/src/lib/server/contact-email-history.js.map +1 -0
  601. package/src/lib/server/contact-profile.d.ts +41 -0
  602. package/src/lib/server/contact-profile.js +45 -0
  603. package/src/lib/server/contact-profile.js.map +1 -0
  604. package/src/lib/server/contact-update.d.ts +92 -0
  605. package/src/lib/server/contact-update.js +512 -0
  606. package/src/lib/server/contact-update.js.map +1 -0
  607. package/src/lib/server/contacts-import.d.ts +73 -0
  608. package/src/lib/server/contacts-import.js +263 -0
  609. package/src/lib/server/contacts-import.js.map +1 -0
  610. package/src/lib/server/contacts-merge.d.ts +86 -0
  611. package/src/lib/server/contacts-merge.js +206 -0
  612. package/src/lib/server/contacts-merge.js.map +1 -0
  613. package/src/lib/server/deals-import.d.ts +76 -0
  614. package/src/lib/server/deals-import.js +246 -0
  615. package/src/lib/server/deals-import.js.map +1 -0
  616. package/src/lib/server/email-send.d.ts +119 -0
  617. package/src/lib/server/email-send.js +667 -0
  618. package/src/lib/server/email-send.js.map +1 -0
  619. package/src/lib/server/email-template-duplicate.d.ts +19 -0
  620. package/src/lib/server/email-template-duplicate.js +206 -0
  621. package/src/lib/server/email-template-duplicate.js.map +1 -0
  622. package/src/lib/server/erase-person.d.ts +108 -0
  623. package/src/lib/server/erase-person.js +309 -0
  624. package/src/lib/server/erase-person.js.map +1 -0
  625. package/src/lib/server/import-context.d.ts +85 -0
  626. package/src/lib/server/import-context.js +181 -0
  627. package/src/lib/server/import-context.js.map +1 -0
  628. package/src/lib/server/inbound-address.d.ts +61 -0
  629. package/src/lib/server/inbound-address.js +188 -0
  630. package/src/lib/server/inbound-address.js.map +1 -0
  631. package/src/lib/server/lead-convert.d.ts +78 -0
  632. package/src/lib/server/lead-convert.js +250 -0
  633. package/src/lib/server/lead-convert.js.map +1 -0
  634. package/src/lib/server/leads-import.d.ts +84 -0
  635. package/src/lib/server/leads-import.js +261 -0
  636. package/src/lib/server/leads-import.js.map +1 -0
  637. package/src/lib/server/next-activity-routes.d.ts +33 -0
  638. package/src/lib/server/next-activity-routes.js +110 -0
  639. package/src/lib/server/next-activity-routes.js.map +1 -0
  640. package/src/lib/server/org-activity.d.ts +61 -0
  641. package/src/lib/server/org-activity.js +120 -0
  642. package/src/lib/server/org-activity.js.map +1 -0
  643. package/src/lib/server/org-caller.d.ts +110 -0
  644. package/src/lib/server/org-caller.js +154 -0
  645. package/src/lib/server/org-caller.js.map +1 -0
  646. package/src/lib/server/recipe-routes.d.ts +75 -0
  647. package/src/lib/server/recipe-routes.js +442 -0
  648. package/src/lib/server/recipe-routes.js.map +1 -0
  649. package/src/lib/server/record-facts.d.ts +65 -0
  650. package/src/lib/server/record-facts.js +337 -0
  651. package/src/lib/server/record-facts.js.map +1 -0
  652. package/src/lib/server/record-timeline.d.ts +51 -0
  653. package/src/lib/server/record-timeline.js +215 -0
  654. package/src/lib/server/record-timeline.js.map +1 -0
  655. package/src/lib/server/suite-gate.d.ts +42 -0
  656. package/src/lib/server/suite-gate.js +87 -0
  657. package/src/lib/server/suite-gate.js.map +1 -0
  658. package/src/lib/server/task-routes.d.ts +132 -0
  659. package/src/lib/server/task-routes.js +699 -0
  660. package/src/lib/server/task-routes.js.map +1 -0
  661. package/src/lib/server/tasks-import.d.ts +54 -0
  662. package/src/lib/server/tasks-import.js +157 -0
  663. package/src/lib/server/tasks-import.js.map +1 -0
  664. package/src/lib/server-deal-stage.d.ts +88 -0
  665. package/src/lib/server-deal-stage.js +316 -0
  666. package/src/lib/server-deal-stage.js.map +1 -0
  667. package/src/lib/server.d.ts +149 -0
  668. package/src/lib/server.js +615 -0
  669. package/src/lib/server.js.map +1 -0
@@ -0,0 +1,316 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ /**
18
+ * `POST /api/crm/deal-stage` — the one writer of a deal's stage (AGL-2598).
19
+ *
20
+ * ## Why a route, when the rules would let the browser do it
21
+ *
22
+ * A deal's title, amount and owner are edited client-direct against the
23
+ * Firestore rules, and nothing about a stage change needs a server to be
24
+ * SAFE. What it needs a server for is to be HEARD: a move between stages, a
25
+ * win and a loss are the three moments an automation wants — "when a deal is
26
+ * won, email the owner", "when one reaches negotiation, file a task" — and a
27
+ * workflow only fires on an event the tenant runtime emits. A stage written
28
+ * by the browser would be a fact nothing could react to. So every surface
29
+ * that moves a deal calls here, and this handler updates the document and
30
+ * then emits `dealStageChanged`, `dealWon` or `dealLost` with a flat payload
31
+ * a workflow filter can read.
32
+ *
33
+ * ## Who may call it
34
+ *
35
+ * Three gates, in the order the cheapest fails first:
36
+ *
37
+ * 1. A verified Firebase session — the console's `authorizedFetch` puts the
38
+ * id token on every call.
39
+ * 2. An admin or editor role ON THIS SITE, resolved by `hostRoleFor` from
40
+ * the org member document, which is the same projection the rules read.
41
+ * 3. The `data.manage` permission in the org — the key the whole CRM is
42
+ * gated on, resolved through the custom-role and per-member layers by
43
+ * `memberHasOrgPermission`, because a member document alone cannot say
44
+ * what a custom role took away.
45
+ *
46
+ * And then the deal has to be VISIBLE to the site: its `visibleTo` must
47
+ * intersect the scope tokens a contact captured on this site would carry.
48
+ * The Admin SDK evaluates no rules, so without this check an editor of one
49
+ * site in an agency could move another client's deals by id.
50
+ *
51
+ * ## The organization variant (AGL-2634)
52
+ *
53
+ * `{ orgId, dealId, … }` instead of a site: the org-level hub's board. The
54
+ * caller is authorized by the ORG — an org-wide member holding
55
+ * `data.manage`, the org hub's own gate — and no visibility check is made,
56
+ * because an org-wide member reads every row the org holds. The event
57
+ * still goes to the deal's own capturing site, which is where the
58
+ * automations that listen for it live; a deal no site captured has none to
59
+ * tell. And the act is logged in the org's feed, since there is no one
60
+ * site's feed it happened in.
61
+ *
62
+ * ## What it writes
63
+ *
64
+ * `stageId`, `status` (from the target stage's `kind`, never from the body),
65
+ * `stageChangedAtMs`, `closedAtMs` (set on a close, cleared on a reopen) and
66
+ * `lostReason` (kept on a loss, removed on anything else). A move to the
67
+ * stage the deal is already in writes nothing and emits nothing — an
68
+ * automation must not fire twice because a card was dropped where it was.
69
+ *
70
+ * ## A won deal makes its contact a customer (AGL-2641)
71
+ *
72
+ * A win is the same fact as a purchase — the business has decided this
73
+ * person bought — and an order already floors a contact's lifecycle stage
74
+ * at `customer` on capture. So the transition INTO `won` applies the same
75
+ * floor to the contact the deal names, in the same write path, behind no
76
+ * setting: `floorContactLifecycleStage` fills an empty stage or advances an
77
+ * earlier one inside the facet of the site the deal was made on, and never
78
+ * moves anybody back — a customer stays a customer, an evangelist an
79
+ * evangelist. When the stage did move, `contactStageChanged` is announced
80
+ * after `dealWon`, so an automation keyed on "became a customer" hears it,
81
+ * and the org's activity line says so. A failure to write the contact does
82
+ * not undo the win: the deal is already closed, and the response reports
83
+ * `customer: null` rather than a 500 for a stage change that did happen.
84
+ */ import { CRM_COLLECTIONS, dealStageById, hostRoleFor, hostScopeToken, ORG_SCOPE_TOKEN } from "@aglyn/aglyn/server";
85
+ import { consentGroupForSite, firebaseAdmin, floorContactLifecycleStage, getOrgForHost, logOrgActivity, memberHasOrgPermission, resolveOrgMembership } from "@aglyn/tenant-data-admin";
86
+ import { isRefusedIdToken } from "@aglyn/tenant-data-admin/server/id-token-refusal";
87
+ import { emitHostEvent } from "@aglyn/tenant-runtime";
88
+ import { FieldValue } from "firebase-admin/firestore";
89
+ import { closingStage, dealEventName, dealEventPayload } from "./model/deal-board-model.js";
90
+ import { authorizeOrgCaller, readCrmRouteScope } from "./server/org-caller.js";
91
+ import { crmSuiteRefusal } from "./server/suite-gate.js";
92
+ /** The most a lost reason may carry — a sentence or two, not a post-mortem. */ export const LOST_REASON_MAX = 500;
93
+ export const crmDealStageHandler = async (req, res)=>{
94
+ var _ref, _ref1, _deal_pipelineId, _deal_stageId, _deal_hostId, _deal_contactId;
95
+ var _req_body, _req_body1, _req_body2, _req_body3;
96
+ if (req.method !== 'POST') {
97
+ res.setHeader('Allow', 'POST');
98
+ return res.status(405).json({
99
+ error: 'Method not allowed'
100
+ });
101
+ }
102
+ const routeScope = readCrmRouteScope(req.body);
103
+ const dealId = String((_ref = (_req_body = req.body) == null ? void 0 : _req_body.dealId) != null ? _ref : '').trim();
104
+ const stageId = typeof ((_req_body1 = req.body) == null ? void 0 : _req_body1.stageId) === 'string' ? req.body.stageId.trim() : '';
105
+ const status = (_req_body2 = req.body) == null ? void 0 : _req_body2.status;
106
+ const closing = status === 'won' || status === 'lost' ? status : null;
107
+ const lostReason = String((_ref1 = (_req_body3 = req.body) == null ? void 0 : _req_body3.lostReason) != null ? _ref1 : '').trim().slice(0, LOST_REASON_MAX);
108
+ if (!routeScope || !dealId) {
109
+ return res.status(400).json({
110
+ error: 'Missing hostId or dealId'
111
+ });
112
+ }
113
+ if (!stageId && !closing) {
114
+ return res.status(400).json({
115
+ error: 'Name a stageId to move to, or a status of won or lost.'
116
+ });
117
+ }
118
+ /*
119
+ * Who is calling, and the org whose deal it is. The site variant
120
+ * resolves the org from the site and the caller's role on it; the org
121
+ * variant is authorized by the org itself, and the site the body may
122
+ * name beside it is not consulted — the deal's own site, read off the
123
+ * document, is the one its event goes to.
124
+ */ let orgId;
125
+ let org;
126
+ let actor = null;
127
+ if (routeScope.level === 'org') {
128
+ const caller = await authorizeOrgCaller(req, routeScope.orgId, {
129
+ needs: 'data.manage',
130
+ refusal: 'Moving a deal at the organization level requires the "Manage data" ' + 'permission across the whole workspace.'
131
+ });
132
+ if (caller.ok === false) {
133
+ return res.status(caller.status).json({
134
+ error: caller.error
135
+ });
136
+ }
137
+ orgId = caller.orgId;
138
+ org = caller.org;
139
+ actor = {
140
+ uid: caller.uid,
141
+ email: caller.email
142
+ };
143
+ } else {
144
+ var _req_headers_authorization;
145
+ const authorization = String((_req_headers_authorization = req.headers.authorization) != null ? _req_headers_authorization : '');
146
+ const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : '';
147
+ if (!idToken) {
148
+ return res.status(401).json({
149
+ error: 'Unauthenticated'
150
+ });
151
+ }
152
+ let uid;
153
+ try {
154
+ uid = (await firebaseAdmin.app().auth().verifyIdToken(idToken)).uid;
155
+ } catch (error) {
156
+ // A refused credential is the caller's 401; a failure to check one is
157
+ // ours and keeps a 5xx (AGL-2852).
158
+ if (isRefusedIdToken(error)) return res.status(401).json({
159
+ error: 'Unauthenticated'
160
+ });
161
+ console.error('[crm] deal-stage could not verify the caller', error);
162
+ return res.status(500).json({
163
+ error: 'The sign-in could not be checked. Try again.'
164
+ });
165
+ }
166
+ const owner = await getOrgForHost(routeScope.hostId).catch(()=>null);
167
+ if (!owner) {
168
+ return res.status(404).json({
169
+ error: 'This site has no organization, so it has no deals.'
170
+ });
171
+ }
172
+ const membership = await resolveOrgMembership(uid, owner.orgId).catch(()=>null);
173
+ const member = membership == null ? void 0 : membership.member;
174
+ const hostRole = hostRoleFor(member, routeScope.hostId);
175
+ if (!member || hostRole !== 'admin' && hostRole !== 'editor') {
176
+ return res.status(403).json({
177
+ error: 'Moving a deal needs an admin or editor role on this site.'
178
+ });
179
+ }
180
+ if (!await memberHasOrgPermission(owner.orgId, member, 'data.manage')) {
181
+ return res.status(403).json({
182
+ error: 'Moving a deal requires the "Manage data" permission.'
183
+ });
184
+ }
185
+ orgId = owner.orgId;
186
+ org = owner.org;
187
+ }
188
+ // Deals are the CRM suite's, at either level (AGL-2787).
189
+ const suite = crmSuiteRefusal(org, 'Moving a deal through its pipeline');
190
+ if (suite) return res.status(suite.status).json(suite.body);
191
+ const firestore = firebaseAdmin.app().firestore();
192
+ const orgRef = firestore.collection('orgs').doc(orgId);
193
+ const dealRef = orgRef.collection(CRM_COLLECTIONS.deals).doc(dealId);
194
+ const dealSnapshot = await dealRef.get();
195
+ if (!dealSnapshot.exists) {
196
+ return res.status(404).json({
197
+ error: 'Unknown deal'
198
+ });
199
+ }
200
+ const deal = dealSnapshot.data();
201
+ if (routeScope.level === 'site') {
202
+ var _deal_visibleTo;
203
+ const group = await consentGroupForSite(routeScope.hostId, org);
204
+ const readable = new Set([
205
+ ORG_SCOPE_TOKEN,
206
+ ...group.hostIds.map(hostScopeToken)
207
+ ]);
208
+ if (!((_deal_visibleTo = deal.visibleTo) != null ? _deal_visibleTo : []).some((token)=>readable.has(token))) {
209
+ return res.status(403).json({
210
+ error: 'This deal is not visible to this site.'
211
+ });
212
+ }
213
+ }
214
+ const pipelineSnapshot = await orgRef.collection(CRM_COLLECTIONS.pipelines).doc(String((_deal_pipelineId = deal.pipelineId) != null ? _deal_pipelineId : '')).get();
215
+ if (!pipelineSnapshot.exists) {
216
+ return res.status(409).json({
217
+ error: "This deal's pipeline no longer exists, so it has no stages to move to."
218
+ });
219
+ }
220
+ const pipeline = pipelineSnapshot.data();
221
+ const target = stageId ? dealStageById(pipeline, stageId) : closingStage(pipeline, closing);
222
+ if (!target) {
223
+ return res.status(400).json({
224
+ error: stageId ? 'This pipeline has no such stage.' : `This pipeline has no ${closing} stage.`
225
+ });
226
+ }
227
+ const previousStageId = String((_deal_stageId = deal.stageId) != null ? _deal_stageId : '');
228
+ const nextStatus = target.kind;
229
+ if (target.id === previousStageId && deal.status === nextStatus) {
230
+ return res.status(200).json({
231
+ ok: true,
232
+ dealId,
233
+ stageId: target.id,
234
+ status: nextStatus,
235
+ previousStageId,
236
+ event: null
237
+ });
238
+ }
239
+ const nowMs = Date.now();
240
+ await dealRef.update({
241
+ stageId: target.id,
242
+ status: nextStatus,
243
+ stageChangedAtMs: nowMs,
244
+ closedAtMs: nextStatus === 'open' ? null : nowMs,
245
+ lostReason: nextStatus === 'lost' ? lostReason : FieldValue.delete(),
246
+ updatedAt: new Date()
247
+ });
248
+ const event = dealEventName(nextStatus);
249
+ // The site whose automations hear the move: the mounted site, or at the
250
+ // organization level the deal's own — a deal no site captured has none.
251
+ const eventHostId = routeScope.level === 'site' ? routeScope.hostId : String((_deal_hostId = deal.hostId) != null ? _deal_hostId : '').trim();
252
+ /*
253
+ * The customer floor, on the transition into `won` alone: a move between
254
+ * open stages, a loss and a reopen say nothing about whether the person
255
+ * bought. The facet written is the site's the deal was made on — under
256
+ * a site the mounted one, at the organization level the deal's own, and
257
+ * for a deal no site captured the person's own capturing site.
258
+ */ let customer = null;
259
+ const contactId = String((_deal_contactId = deal.contactId) != null ? _deal_contactId : '').trim();
260
+ if (nextStatus === 'won' && contactId) {
261
+ customer = await floorContactLifecycleStage({
262
+ contactRef: orgRef.collection('contacts').doc(contactId),
263
+ org,
264
+ hostId: eventHostId || null,
265
+ floor: 'customer'
266
+ }).catch((error)=>{
267
+ console.error('[crm] deal-stage: the customer floor failed', dealId, contactId, error);
268
+ return null;
269
+ });
270
+ }
271
+ const becameCustomer = (customer == null ? void 0 : customer.outcome) === 'advanced';
272
+ if (eventHostId) {
273
+ await emitHostEvent(eventHostId, event, dealEventPayload(dealId, _extends({}, deal, {
274
+ stageId: target.id,
275
+ lostReason: nextStatus === 'lost' ? lostReason : undefined
276
+ }), previousStageId));
277
+ }
278
+ if ((customer == null ? void 0 : customer.outcome) === 'advanced') {
279
+ // The stage change is the win's effect, announced after its cause, to
280
+ // the site whose facet moved — the same site as the win's, unless no
281
+ // site captured the deal and the person's own site holds the stage.
282
+ await emitHostEvent(customer.hostId, 'contactStageChanged', {
283
+ contactId: customer.contactId,
284
+ email: customer.email,
285
+ lifecycleStage: customer.lifecycleStage,
286
+ previousStage: customer.previousStage
287
+ });
288
+ }
289
+ if (actor) {
290
+ var _deal_title;
291
+ await logOrgActivity(orgId, actor, nextStatus === 'won' ? becameCustomer ? 'Marked deal won — contact now a customer' : 'Marked deal won' : nextStatus === 'lost' ? 'Marked deal lost' : `Moved deal to ${target.name}`, {
292
+ type: 'deal',
293
+ id: dealId,
294
+ name: String((_deal_title = deal.title) != null ? _deal_title : '')
295
+ });
296
+ }
297
+ return res.status(200).json({
298
+ ok: true,
299
+ dealId,
300
+ stageId: target.id,
301
+ status: nextStatus,
302
+ previousStageId,
303
+ event,
304
+ /*
305
+ * What the win did to the contact: the stage it now holds and whether
306
+ * this call raised it. `null` on anything but a win, on a deal that
307
+ * names no contact, and on a contact write that failed.
308
+ */ customer: customer && (customer.outcome === 'advanced' || customer.outcome === 'held') ? {
309
+ contactId: customer.contactId,
310
+ lifecycleStage: customer.lifecycleStage,
311
+ advanced: customer.outcome === 'advanced'
312
+ } : null
313
+ });
314
+ };
315
+
316
+ //# sourceMappingURL=server-deal-stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/plugins/crm/src/lib/server-deal-stage.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * `POST /api/crm/deal-stage` — the one writer of a deal's stage (AGL-2598).\n *\n * ## Why a route, when the rules would let the browser do it\n *\n * A deal's title, amount and owner are edited client-direct against the\n * Firestore rules, and nothing about a stage change needs a server to be\n * SAFE. What it needs a server for is to be HEARD: a move between stages, a\n * win and a loss are the three moments an automation wants — \"when a deal is\n * won, email the owner\", \"when one reaches negotiation, file a task\" — and a\n * workflow only fires on an event the tenant runtime emits. A stage written\n * by the browser would be a fact nothing could react to. So every surface\n * that moves a deal calls here, and this handler updates the document and\n * then emits `dealStageChanged`, `dealWon` or `dealLost` with a flat payload\n * a workflow filter can read.\n *\n * ## Who may call it\n *\n * Three gates, in the order the cheapest fails first:\n *\n * 1. A verified Firebase session — the console's `authorizedFetch` puts the\n * id token on every call.\n * 2. An admin or editor role ON THIS SITE, resolved by `hostRoleFor` from\n * the org member document, which is the same projection the rules read.\n * 3. The `data.manage` permission in the org — the key the whole CRM is\n * gated on, resolved through the custom-role and per-member layers by\n * `memberHasOrgPermission`, because a member document alone cannot say\n * what a custom role took away.\n *\n * And then the deal has to be VISIBLE to the site: its `visibleTo` must\n * intersect the scope tokens a contact captured on this site would carry.\n * The Admin SDK evaluates no rules, so without this check an editor of one\n * site in an agency could move another client's deals by id.\n *\n * ## The organization variant (AGL-2634)\n *\n * `{ orgId, dealId, … }` instead of a site: the org-level hub's board. The\n * caller is authorized by the ORG — an org-wide member holding\n * `data.manage`, the org hub's own gate — and no visibility check is made,\n * because an org-wide member reads every row the org holds. The event\n * still goes to the deal's own capturing site, which is where the\n * automations that listen for it live; a deal no site captured has none to\n * tell. And the act is logged in the org's feed, since there is no one\n * site's feed it happened in.\n *\n * ## What it writes\n *\n * `stageId`, `status` (from the target stage's `kind`, never from the body),\n * `stageChangedAtMs`, `closedAtMs` (set on a close, cleared on a reopen) and\n * `lostReason` (kept on a loss, removed on anything else). A move to the\n * stage the deal is already in writes nothing and emits nothing — an\n * automation must not fire twice because a card was dropped where it was.\n *\n * ## A won deal makes its contact a customer (AGL-2641)\n *\n * A win is the same fact as a purchase — the business has decided this\n * person bought — and an order already floors a contact's lifecycle stage\n * at `customer` on capture. So the transition INTO `won` applies the same\n * floor to the contact the deal names, in the same write path, behind no\n * setting: `floorContactLifecycleStage` fills an empty stage or advances an\n * earlier one inside the facet of the site the deal was made on, and never\n * moves anybody back — a customer stays a customer, an evangelist an\n * evangelist. When the stage did move, `contactStageChanged` is announced\n * after `dealWon`, so an automation keyed on \"became a customer\" hears it,\n * and the org's activity line says so. A failure to write the contact does\n * not undo the win: the deal is already closed, and the response reports\n * `customer: null` rather than a 500 for a stage change that did happen.\n */\n\nimport {\n CRM_COLLECTIONS,\n type CrmDeal,\n type CrmPipeline,\n dealStageById,\n hostRoleFor,\n hostScopeToken,\n ORG_SCOPE_TOKEN,\n type PluginApiHandler,\n} from '@aglyn/aglyn/server'\nimport {\n consentGroupForSite,\n type ContactLifecycleFloor,\n firebaseAdmin,\n floorContactLifecycleStage,\n getOrgForHost,\n logOrgActivity,\n memberHasOrgPermission,\n resolveOrgMembership,\n} from '@aglyn/tenant-data-admin'\nimport { isRefusedIdToken } from '@aglyn/tenant-data-admin/server/id-token-refusal'\nimport { emitHostEvent } from '@aglyn/tenant-runtime'\nimport { FieldValue } from 'firebase-admin/firestore'\nimport {\n closingStage,\n dealEventName,\n dealEventPayload,\n} from './model/deal-board-model'\nimport { authorizeOrgCaller, readCrmRouteScope } from './server/org-caller'\nimport { crmSuiteRefusal } from './server/suite-gate'\n\n/** The most a lost reason may carry — a sentence or two, not a post-mortem. */\nexport const LOST_REASON_MAX = 500\n\nexport const crmDealStageHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') {\n res.setHeader('Allow', 'POST')\n return res.status(405).json({ error: 'Method not allowed' })\n }\n\n const routeScope = readCrmRouteScope(req.body as Record<string, unknown>)\n const dealId = String(req.body?.dealId ?? '').trim()\n const stageId =\n typeof req.body?.stageId === 'string' ? req.body.stageId.trim() : ''\n const status = req.body?.status\n const closing = status === 'won' || status === 'lost' ? status : null\n const lostReason = String(req.body?.lostReason ?? '')\n .trim()\n .slice(0, LOST_REASON_MAX)\n if (!routeScope || !dealId) {\n return res.status(400).json({ error: 'Missing hostId or dealId' })\n }\n if (!stageId && !closing) {\n return res.status(400).json({\n error: 'Name a stageId to move to, or a status of won or lost.',\n })\n }\n\n /*\n * Who is calling, and the org whose deal it is. The site variant\n * resolves the org from the site and the caller's role on it; the org\n * variant is authorized by the org itself, and the site the body may\n * name beside it is not consulted — the deal's own site, read off the\n * document, is the one its event goes to.\n */\n let orgId: string\n let org: Record<string, unknown>\n let actor: { uid: string; email: string | null } | null = null\n if (routeScope.level === 'org') {\n const caller = await authorizeOrgCaller(req, routeScope.orgId, {\n needs: 'data.manage',\n refusal:\n 'Moving a deal at the organization level requires the \"Manage data\" ' +\n 'permission across the whole workspace.',\n })\n if (caller.ok === false) {\n return res.status(caller.status).json({ error: caller.error })\n }\n orgId = caller.orgId\n org = caller.org as Record<string, unknown>\n actor = { uid: caller.uid, email: caller.email }\n } else {\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ')\n ? authorization.slice('Bearer '.length)\n : ''\n if (!idToken) {\n return res.status(401).json({ error: 'Unauthenticated' })\n }\n let uid: string\n try {\n uid = (await firebaseAdmin.app().auth().verifyIdToken(idToken)).uid\n } catch (error) {\n // A refused credential is the caller's 401; a failure to check one is\n // ours and keeps a 5xx (AGL-2852).\n if (isRefusedIdToken(error)) return res.status(401).json({ error: 'Unauthenticated' })\n console.error('[crm] deal-stage could not verify the caller', error)\n return res.status(500).json({ error: 'The sign-in could not be checked. Try again.' })\n }\n\n const owner = await getOrgForHost(routeScope.hostId).catch(() => null)\n if (!owner) {\n return res.status(404).json({\n error: 'This site has no organization, so it has no deals.',\n })\n }\n const membership = await resolveOrgMembership(uid, owner.orgId).catch(\n () => null,\n )\n const member = membership?.member\n const hostRole = hostRoleFor(member, routeScope.hostId)\n if (!member || (hostRole !== 'admin' && hostRole !== 'editor')) {\n return res.status(403).json({\n error: 'Moving a deal needs an admin or editor role on this site.',\n })\n }\n if (!(await memberHasOrgPermission(owner.orgId, member, 'data.manage'))) {\n return res.status(403).json({\n error: 'Moving a deal requires the \"Manage data\" permission.',\n })\n }\n orgId = owner.orgId\n org = owner.org as Record<string, unknown>\n }\n\n // Deals are the CRM suite's, at either level (AGL-2787).\n const suite = crmSuiteRefusal(org, 'Moving a deal through its pipeline')\n if (suite) return res.status(suite.status).json(suite.body)\n\n const firestore = firebaseAdmin.app().firestore()\n const orgRef = firestore.collection('orgs').doc(orgId)\n const dealRef = orgRef.collection(CRM_COLLECTIONS.deals).doc(dealId)\n const dealSnapshot = await dealRef.get()\n if (!dealSnapshot.exists) {\n return res.status(404).json({ error: 'Unknown deal' })\n }\n const deal = dealSnapshot.data() as CrmDeal\n\n if (routeScope.level === 'site') {\n const group = await consentGroupForSite(routeScope.hostId, org)\n const readable = new Set<string>([\n ORG_SCOPE_TOKEN,\n ...group.hostIds.map(hostScopeToken),\n ])\n if (!(deal.visibleTo ?? []).some((token) => readable.has(token))) {\n return res.status(403).json({ error: 'This deal is not visible to this site.' })\n }\n }\n\n const pipelineSnapshot = await orgRef\n .collection(CRM_COLLECTIONS.pipelines)\n .doc(String(deal.pipelineId ?? ''))\n .get()\n if (!pipelineSnapshot.exists) {\n return res.status(409).json({\n error: \"This deal's pipeline no longer exists, so it has no stages to move to.\",\n })\n }\n const pipeline = pipelineSnapshot.data() as CrmPipeline\n const target = stageId\n ? dealStageById(pipeline, stageId)\n : closingStage(pipeline, closing as 'won' | 'lost')\n if (!target) {\n return res.status(400).json({\n error: stageId\n ? 'This pipeline has no such stage.'\n : `This pipeline has no ${closing} stage.`,\n })\n }\n\n const previousStageId = String(deal.stageId ?? '')\n const nextStatus = target.kind\n if (target.id === previousStageId && deal.status === nextStatus) {\n return res.status(200).json({\n ok: true,\n dealId,\n stageId: target.id,\n status: nextStatus,\n previousStageId,\n event: null,\n })\n }\n\n const nowMs = Date.now()\n await dealRef.update({\n stageId: target.id,\n status: nextStatus,\n stageChangedAtMs: nowMs,\n closedAtMs: nextStatus === 'open' ? null : nowMs,\n lostReason: nextStatus === 'lost' ? lostReason : FieldValue.delete(),\n updatedAt: new Date(),\n })\n\n const event = dealEventName(nextStatus)\n // The site whose automations hear the move: the mounted site, or at the\n // organization level the deal's own — a deal no site captured has none.\n const eventHostId =\n routeScope.level === 'site' ? routeScope.hostId : String(deal.hostId ?? '').trim()\n\n /*\n * The customer floor, on the transition into `won` alone: a move between\n * open stages, a loss and a reopen say nothing about whether the person\n * bought. The facet written is the site's the deal was made on — under\n * a site the mounted one, at the organization level the deal's own, and\n * for a deal no site captured the person's own capturing site.\n */\n let customer: ContactLifecycleFloor | null = null\n const contactId = String(deal.contactId ?? '').trim()\n if (nextStatus === 'won' && contactId) {\n customer = await floorContactLifecycleStage({\n contactRef: orgRef.collection('contacts').doc(contactId),\n org,\n hostId: eventHostId || null,\n floor: 'customer',\n }).catch((error: unknown) => {\n console.error('[crm] deal-stage: the customer floor failed', dealId, contactId, error)\n return null\n })\n }\n const becameCustomer = customer?.outcome === 'advanced'\n\n if (eventHostId) {\n await emitHostEvent(\n eventHostId,\n event,\n dealEventPayload(\n dealId,\n {\n ...deal,\n stageId: target.id,\n lostReason: nextStatus === 'lost' ? lostReason : undefined,\n },\n previousStageId,\n ),\n )\n }\n if (customer?.outcome === 'advanced') {\n // The stage change is the win's effect, announced after its cause, to\n // the site whose facet moved — the same site as the win's, unless no\n // site captured the deal and the person's own site holds the stage.\n await emitHostEvent(customer.hostId, 'contactStageChanged', {\n contactId: customer.contactId,\n email: customer.email,\n lifecycleStage: customer.lifecycleStage,\n previousStage: customer.previousStage,\n })\n }\n if (actor) {\n await logOrgActivity(\n orgId,\n actor,\n nextStatus === 'won'\n ? becameCustomer\n ? 'Marked deal won — contact now a customer'\n : 'Marked deal won'\n : nextStatus === 'lost'\n ? 'Marked deal lost'\n : `Moved deal to ${target.name}`,\n { type: 'deal', id: dealId, name: String(deal.title ?? '') },\n )\n }\n\n return res.status(200).json({\n ok: true,\n dealId,\n stageId: target.id,\n status: nextStatus,\n previousStageId,\n event,\n /*\n * What the win did to the contact: the stage it now holds and whether\n * this call raised it. `null` on anything but a win, on a deal that\n * names no contact, and on a contact write that failed.\n */\n customer:\n customer && (customer.outcome === 'advanced' || customer.outcome === 'held')\n ? {\n contactId: customer.contactId,\n lifecycleStage: customer.lifecycleStage,\n advanced: customer.outcome === 'advanced',\n }\n : null,\n })\n}\n"],"names":["CRM_COLLECTIONS","dealStageById","hostRoleFor","hostScopeToken","ORG_SCOPE_TOKEN","consentGroupForSite","firebaseAdmin","floorContactLifecycleStage","getOrgForHost","logOrgActivity","memberHasOrgPermission","resolveOrgMembership","isRefusedIdToken","emitHostEvent","FieldValue","closingStage","dealEventName","dealEventPayload","authorizeOrgCaller","readCrmRouteScope","crmSuiteRefusal","LOST_REASON_MAX","crmDealStageHandler","req","res","deal","method","setHeader","status","json","error","routeScope","body","dealId","String","trim","stageId","closing","lostReason","slice","orgId","org","actor","level","caller","needs","refusal","ok","uid","email","authorization","headers","idToken","startsWith","length","app","auth","verifyIdToken","console","owner","hostId","catch","membership","member","hostRole","suite","firestore","orgRef","collection","doc","dealRef","deals","dealSnapshot","get","exists","data","group","readable","Set","hostIds","map","visibleTo","some","token","has","pipelineSnapshot","pipelines","pipelineId","pipeline","target","previousStageId","nextStatus","kind","id","event","nowMs","Date","now","update","stageChangedAtMs","closedAtMs","delete","updatedAt","eventHostId","customer","contactId","contactRef","floor","becameCustomer","outcome","undefined","lifecycleStage","previousStage","name","type","title","advanced"],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * The Contacts plugin's SERVER half (AGL-2595).
19
+ *
20
+ * Contacts CRM v1 had none: every console write was client-direct against
21
+ * the Firestore rules, and the one server path that creates a contact —
22
+ * `upsertHostContact` — belongs to the capture doors, not to this plugin.
23
+ * v2 needs a server for the things a browser must not do alone: an import
24
+ * that dedupes forty thousand rows, a bulk action over a selection, an
25
+ * auto-association of contacts to companies by domain. Each of those lands
26
+ * as a `crm/<route>` handler registered here.
27
+ *
28
+ * `crm/ping` exists so the wiring is PROVEN rather than assumed:
29
+ * `plugins.config.json` names this module's register function and the
30
+ * `crm` API prefix, the generated server manifest loads this file, and the
31
+ * console's `/api/[...pluginApi]` dispatcher reaches the handler. A plugin
32
+ * whose first real route also had to be its first wiring test would have
33
+ * two things to debug at once.
34
+ *
35
+ * The real routes are the writes with a side effect outside the document:
36
+ * `crm/contact-stage` (AGL-2605) exists for the EVENT — `contactStageChanged`
37
+ * can only be emitted by a server path that performed the write, so a record
38
+ * page that moved the stage client-direct would move the person and tell no
39
+ * automation; the task routes (AGL-2599) carry an assignee's notification and
40
+ * the `taskCompleted` event; `crm/contacts-import` (AGL-2602) pushes one chunk
41
+ * of a file through the same capture door every other server door uses.
42
+ * `crm/deal-stage` (AGL-2598) is the one writer of a deal's stage, won and lost,
43
+ * because a stage change is what automations listen for (`server-deal-stage.ts`).
44
+ * `crm/contacts-create` (AGL-2596) is a person typed into the console by a
45
+ * member of the team — a server route because the dedupe against every
46
+ * holder's rows and the audience band are judgments the browser cannot make.
47
+ * `crm/contact-update` (AGL-2804) is every other write to a contact's facets:
48
+ * the rules cannot tell one field of a holder's facet from another, so they
49
+ * leave a client nothing there but letting a holder go, and the plan is
50
+ * asked here about the fields a save carries.
51
+ */
52
+ import { type PluginApiHandler } from '@aglyn/aglyn/server';
53
+ /**
54
+ * `GET /api/crm/ping` → `{ ok: true, plugin: 'crm' }`.
55
+ *
56
+ * No auth, no host, no data: it answers whether the plugin's server bundle
57
+ * was loaded and its routes registered, which is a fact about the process
58
+ * and not about any org. Anything that reads a document goes behind the
59
+ * same session and role checks the other plugins' console routes use.
60
+ */
61
+ export declare const crmPingHandler: PluginApiHandler;
62
+ /**
63
+ * `POST /api/crm/contact-stage` with `{ hostId, contactId, lifecycleStage }`.
64
+ *
65
+ * Writes the stage into THIS site's facet on the contact — a dotted
66
+ * `update()`, never a top-level field, because the row is shared by every
67
+ * site in the org and a stage is one holder's reading of the person — and
68
+ * then announces `contactStageChanged` with the stage it replaced.
69
+ *
70
+ * A stage set to what it already is writes nothing and announces nothing:
71
+ * the response says `changed: false`, and no automation listening for a
72
+ * change hears one that did not happen.
73
+ *
74
+ * `lifecycleStage: null` CLEARS the stage (AGL-2804). A facet is the
75
+ * server's to write, so "not placed yet" comes through the route that owns
76
+ * the stage rather than as a client-direct delete, and it is refused to a
77
+ * plan without the suite the way a move is. There is no event for "no
78
+ * stage", so a clear announces nothing; an empty string names no stage and
79
+ * is refused like any other the list does not have.
80
+ *
81
+ * The contact is looked up by id and then checked against `visibleTo`,
82
+ * because the Admin SDK evaluates no rules: a caller who can edit site A
83
+ * must not be able to restage a contact only site B holds by guessing its
84
+ * id, and the scoped query the list uses is not available to a `doc()` read.
85
+ */
86
+ export declare const contactStageHandler: PluginApiHandler;
87
+ /**
88
+ * What the create route says when the band refused (AGL-2596).
89
+ *
90
+ * The contacts list's own alert, in the past tense: the list says new
91
+ * visitors are "no longer captured", and this says the one contact the
92
+ * reader just tried to add was not. The remedy is the same sentence in both
93
+ * places, so a reader who sees one and then the other is told one thing.
94
+ */
95
+ export declare const CONTACT_BAND_FULL_MESSAGE: string;
96
+ /**
97
+ * `POST /api/crm/contacts-create` — a person added by hand (AGL-2596).
98
+ *
99
+ * Body: `{ hostId, email, name?, phone?, jobTitle?, companyName?,
100
+ * companyId?, address?, ownerUid?, lifecycleStage?, tags?,
101
+ * marketingConsent? }`. Answers `{ contactId, created }`: `created` is
102
+ * false when the address already belonged to somebody, in which case what
103
+ * was typed MERGES into the existing row — the dedupe the shared address
104
+ * book exists for, and the reason a second "create" of one person is not
105
+ * an error.
106
+ *
107
+ * ## Who may call it
108
+ *
109
+ * The caller's ID token, then `data.manage` on the site's org — the same key
110
+ * the console surface itself is gated on, resolved through the same
111
+ * three-layer permission read the members route uses. A scoped member is
112
+ * admitted only for a site they reach: the rules would refuse a browser
113
+ * write outside their tokens, and a server route that admitted it would be
114
+ * a way round the rules rather than a service in front of them.
115
+ *
116
+ * ## What it refuses, and how
117
+ *
118
+ * A malformed email or phone number is a 400 with a sentence the drawer can
119
+ * show under the field. The band is a 409 carrying the list's own wording:
120
+ * it is not a bad request and not a server fault, it is the plan saying no,
121
+ * and the drawer relays the sentence rather than inventing one.
122
+ *
123
+ * ## The company (AGL-2613)
124
+ *
125
+ * `companyId` is the picker's choice, and it is checked before anything is
126
+ * written: the company has to exist and be visible to the capturing site's
127
+ * scope, or a caller could file a person under a record they cannot open —
128
+ * the same refusal the lead conversion makes. It reaches the upsert as
129
+ * `facet.companyId`, which is where the link is kept in step with its mirror
130
+ * and the company's contacts count; a merge onto somebody already at another
131
+ * company is a MOVE there, not a second link. The stored company's own name
132
+ * is what is echoed, over whatever the client sent, because the name on the
133
+ * record is the company's and not the form's.
134
+ *
135
+ * ## What it writes beyond the upsert
136
+ *
137
+ * `upsertHostContact` takes the profile — phone, title, address, owner,
138
+ * stage, company — and writes it into the capturing group's facet. The two
139
+ * things it does not take are written here by DOTTED path afterwards: the
140
+ * tags, which union into whatever the person already carried, and the
141
+ * company name — the picked company's, or free text for a person filed
142
+ * under a name no company record carries yet. Dotted paths because this is
143
+ * an `update()`, and only an update reads a dot as a path — a nested object
144
+ * here would replace the facet map and take every other holder's records
145
+ * with it.
146
+ */
147
+ export declare const crmContactsCreateHandler: PluginApiHandler;
148
+ /** Console API registration, named in `plugins.config.json` as `consoleApi`. */
149
+ export declare function registerCrmConsoleApi(): void;