@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,120 @@
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
+ * `POST /api/crm/org-activity` — one line in the organization's activity
18
+ * feed (AGL-2634).
19
+ *
20
+ * Body: `{ orgId, action, target: { type, id?, name? } }`. Answers
21
+ * `{ ok: true }` once the line is appended.
22
+ *
23
+ * ## Why a route, when the site feed takes the browser's word for it
24
+ *
25
+ * A site's feed at `hosts/{hostId}/activity` is written client-direct: the
26
+ * bulk bars log "Deleted deal" per row through `useHostActivityLogger`,
27
+ * under a rule that lets a member holding a content role append. The
28
+ * organization's feed at `orgs/{orgId}/activity` is not — `allow write: if
29
+ * false` for every client, because the feed names who did what across every
30
+ * site and its only reader is `/api/orgs/activity`, gated on `org.auditLog`
31
+ * with the Admin SDK. So an act performed at the ORGANIZATION level with a
32
+ * client-direct write — a bulk bar over the org's deals, which writes the
33
+ * documents from the browser — has no feed it can reach, and the org hub
34
+ * wrote no line at all for its bulk actions. This is the door: the same
35
+ * trust the site feed extends to the browser (a verified member, holding
36
+ * the permission the CRM is gated on), narrowed to the org hub's reach
37
+ * (org-wide, never a site collaborator) and to the CRM's own record kinds.
38
+ *
39
+ * What it does NOT vouch for is that the act happened: like every
40
+ * client-written feed line, the sentence is the caller's. The routes that
41
+ * perform an org-level act themselves — the stage move, the merge, the
42
+ * erasure, the email — write their own line with the Admin SDK and never
43
+ * call here.
44
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
45
+ import { logOrgActivity } from "@aglyn/tenant-data-admin";
46
+ import { CRM_API_ROUTES, CRM_ORG_ACTIVITY_ACTION_MAX, CRM_ORG_ACTIVITY_KINDS } from "../constants/api-routes.js";
47
+ import { authorizeOrgCaller } from "./org-caller.js";
48
+ import { crmSuiteRefusal } from "./suite-gate.js";
49
+ export const CRM_ORG_ACTIVITY_ROUTE = CRM_API_ROUTES.orgActivity;
50
+ function typed(value, max) {
51
+ return String(value != null ? value : '').trim().slice(0, max);
52
+ }
53
+ const isKind = (value)=>typeof value === 'string' && CRM_ORG_ACTIVITY_KINDS.includes(value);
54
+ export const crmOrgActivityHandler = async (req, res)=>{
55
+ var _req_body;
56
+ if (req.method !== 'POST') {
57
+ res.setHeader('Allow', 'POST');
58
+ res.status(405).json({
59
+ error: 'Method not allowed'
60
+ });
61
+ return;
62
+ }
63
+ const body = typeof req.body === 'string' ? JSON.parse(req.body) : (_req_body = req.body) != null ? _req_body : {};
64
+ const orgId = typed(body.orgId, 128);
65
+ const action = typed(body.action, CRM_ORG_ACTIVITY_ACTION_MAX);
66
+ const target = body.target && typeof body.target === 'object' ? body.target : null;
67
+ if (!orgId || !action || !target) {
68
+ res.status(400).json({
69
+ error: 'Missing orgId, action or target'
70
+ });
71
+ return;
72
+ }
73
+ if (!isKind(target.type)) {
74
+ res.status(400).json({
75
+ error: 'The target names no CRM record kind'
76
+ });
77
+ return;
78
+ }
79
+ const id = typed(target.id, 200);
80
+ const name = typed(target.name, 200);
81
+ try {
82
+ const caller = await authorizeOrgCaller(req, orgId, {
83
+ needs: 'data.manage',
84
+ refusal: 'Logging organization activity requires the data permission across the whole workspace'
85
+ });
86
+ if (caller.ok === false) {
87
+ res.status(caller.status).json({
88
+ error: caller.error
89
+ });
90
+ return;
91
+ }
92
+ // The plan after the caller, before the line is written (AGL-2851).
93
+ const suite = crmSuiteRefusal(caller.org, "Logging a CRM act to the organization's feed");
94
+ if (suite) {
95
+ res.status(suite.status).json(suite.body);
96
+ return;
97
+ }
98
+ await logOrgActivity(orgId, {
99
+ uid: caller.uid,
100
+ email: caller.email
101
+ }, action, _extends({
102
+ type: target.type
103
+ }, id ? {
104
+ id
105
+ } : {}, name ? {
106
+ name
107
+ } : {}));
108
+ res.status(200).json({
109
+ ok: true
110
+ });
111
+ } catch (error) {
112
+ console.error('[crm] org-activity failed', orgId, error);
113
+ res.status(500).json({
114
+ error: 'The activity could not be logged'
115
+ });
116
+ }
117
+ };
118
+ export default crmOrgActivityHandler;
119
+
120
+ //# sourceMappingURL=org-activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/server/org-activity.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/org-activity` — one line in the organization's activity\n * feed (AGL-2634).\n *\n * Body: `{ orgId, action, target: { type, id?, name? } }`. Answers\n * `{ ok: true }` once the line is appended.\n *\n * ## Why a route, when the site feed takes the browser's word for it\n *\n * A site's feed at `hosts/{hostId}/activity` is written client-direct: the\n * bulk bars log \"Deleted deal\" per row through `useHostActivityLogger`,\n * under a rule that lets a member holding a content role append. The\n * organization's feed at `orgs/{orgId}/activity` is not — `allow write: if\n * false` for every client, because the feed names who did what across every\n * site and its only reader is `/api/orgs/activity`, gated on `org.auditLog`\n * with the Admin SDK. So an act performed at the ORGANIZATION level with a\n * client-direct write — a bulk bar over the org's deals, which writes the\n * documents from the browser — has no feed it can reach, and the org hub\n * wrote no line at all for its bulk actions. This is the door: the same\n * trust the site feed extends to the browser (a verified member, holding\n * the permission the CRM is gated on), narrowed to the org hub's reach\n * (org-wide, never a site collaborator) and to the CRM's own record kinds.\n *\n * What it does NOT vouch for is that the act happened: like every\n * client-written feed line, the sentence is the caller's. The routes that\n * perform an org-level act themselves — the stage move, the merge, the\n * erasure, the email — write their own line with the Admin SDK and never\n * call here.\n */\n\nimport type { PluginApiHandler } from '@aglyn/aglyn/server'\nimport { logOrgActivity } from '@aglyn/tenant-data-admin'\nimport {\n CRM_API_ROUTES,\n CRM_ORG_ACTIVITY_ACTION_MAX,\n CRM_ORG_ACTIVITY_KINDS,\n type CrmOrgActivityKind,\n} from '../constants/api-routes'\nimport { authorizeOrgCaller } from './org-caller'\nimport { crmSuiteRefusal } from './suite-gate'\n\nexport const CRM_ORG_ACTIVITY_ROUTE = CRM_API_ROUTES.orgActivity\n\n/** The body the org-level bulk bars post. */\nexport interface OrgActivityRequest {\n orgId: string\n /** The sentence — \"Owner set on 3 deals\" — as the bar's snackbar said it. */\n action: string\n target: {\n type: CrmOrgActivityKind\n id?: string\n name?: string\n }\n}\n\nfunction typed(value: unknown, max: number): string {\n return String(value ?? '')\n .trim()\n .slice(0, max)\n}\n\nconst isKind = (value: unknown): value is CrmOrgActivityKind =>\n typeof value === 'string' &&\n (CRM_ORG_ACTIVITY_KINDS as readonly string[]).includes(value)\n\nexport const crmOrgActivityHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') {\n res.setHeader('Allow', 'POST')\n res.status(405).json({ error: 'Method not allowed' })\n return\n }\n const body: Partial<OrgActivityRequest> =\n typeof req.body === 'string' ? JSON.parse(req.body) : (req.body ?? {})\n const orgId = typed(body.orgId, 128)\n const action = typed(body.action, CRM_ORG_ACTIVITY_ACTION_MAX)\n const target = body.target && typeof body.target === 'object' ? body.target : null\n if (!orgId || !action || !target) {\n res.status(400).json({ error: 'Missing orgId, action or target' })\n return\n }\n if (!isKind(target.type)) {\n res.status(400).json({ error: 'The target names no CRM record kind' })\n return\n }\n const id = typed(target.id, 200)\n const name = typed(target.name, 200)\n\n try {\n const caller = await authorizeOrgCaller(req, orgId, {\n needs: 'data.manage',\n refusal:\n 'Logging organization activity requires the data permission across the whole workspace',\n })\n if (caller.ok === false) {\n res.status(caller.status).json({ error: caller.error })\n return\n }\n // The plan after the caller, before the line is written (AGL-2851).\n const suite = crmSuiteRefusal(caller.org, \"Logging a CRM act to the organization's feed\")\n if (suite) {\n res.status(suite.status).json(suite.body)\n return\n }\n await logOrgActivity(orgId, { uid: caller.uid, email: caller.email }, action, {\n type: target.type,\n ...(id ? { id } : {}),\n ...(name ? { name } : {}),\n })\n res.status(200).json({ ok: true })\n } catch (error) {\n console.error('[crm] org-activity failed', orgId, error)\n res.status(500).json({ error: 'The activity could not be logged' })\n }\n}\n\nexport default crmOrgActivityHandler\n"],"names":["logOrgActivity","CRM_API_ROUTES","CRM_ORG_ACTIVITY_ACTION_MAX","CRM_ORG_ACTIVITY_KINDS","authorizeOrgCaller","crmSuiteRefusal","CRM_ORG_ACTIVITY_ROUTE","orgActivity","typed","value","max","String","trim","slice","isKind","includes","crmOrgActivityHandler","req","res","method","setHeader","status","json","error","body","JSON","parse","orgId","action","target","type","id","name","caller","needs","refusal","ok","suite","org","uid","email","console"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BC;AAGD,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SACEC,cAAc,EACdC,2BAA2B,EAC3BC,sBAAsB,QAEjB,6BAAyB;AAChC,SAASC,kBAAkB,QAAQ,kBAAc;AACjD,SAASC,eAAe,QAAQ,kBAAc;AAE9C,OAAO,MAAMC,yBAAyBL,eAAeM,WAAW,CAAA;AAchE,SAASC,MAAMC,KAAc,EAAEC,GAAW;IACxC,OAAOC,OAAOF,gBAAAA,QAAS,IACpBG,IAAI,GACJC,KAAK,CAAC,GAAGH;AACd;AAEA,MAAMI,SAAS,CAACL,QACd,OAAOA,UAAU,YACjB,AAACN,uBAA6CY,QAAQ,CAACN;AAEzD,OAAO,MAAMO,wBAA0C,OAAOC,KAAKC;QAORD;IANzD,IAAIA,IAAIE,MAAM,KAAK,QAAQ;QACzBD,IAAIE,SAAS,CAAC,SAAS;QACvBF,IAAIG,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAqB;QACnD;IACF;IACA,MAAMC,OACJ,OAAOP,IAAIO,IAAI,KAAK,WAAWC,KAAKC,KAAK,CAACT,IAAIO,IAAI,KAAKP,YAAAA,IAAIO,IAAI,YAARP,YAAY,CAAC;IACtE,MAAMU,QAAQnB,MAAMgB,KAAKG,KAAK,EAAE;IAChC,MAAMC,SAASpB,MAAMgB,KAAKI,MAAM,EAAE1B;IAClC,MAAM2B,SAASL,KAAKK,MAAM,IAAI,OAAOL,KAAKK,MAAM,KAAK,WAAWL,KAAKK,MAAM,GAAG;IAC9E,IAAI,CAACF,SAAS,CAACC,UAAU,CAACC,QAAQ;QAChCX,IAAIG,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAkC;QAChE;IACF;IACA,IAAI,CAACT,OAAOe,OAAOC,IAAI,GAAG;QACxBZ,IAAIG,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAsC;QACpE;IACF;IACA,MAAMQ,KAAKvB,MAAMqB,OAAOE,EAAE,EAAE;IAC5B,MAAMC,OAAOxB,MAAMqB,OAAOG,IAAI,EAAE;IAEhC,IAAI;QACF,MAAMC,SAAS,MAAM7B,mBAAmBa,KAAKU,OAAO;YAClDO,OAAO;YACPC,SACE;QACJ;QACA,IAAIF,OAAOG,EAAE,KAAK,OAAO;YACvBlB,IAAIG,MAAM,CAACY,OAAOZ,MAAM,EAAEC,IAAI,CAAC;gBAAEC,OAAOU,OAAOV,KAAK;YAAC;YACrD;QACF;QACA,oEAAoE;QACpE,MAAMc,QAAQhC,gBAAgB4B,OAAOK,GAAG,EAAE;QAC1C,IAAID,OAAO;YACTnB,IAAIG,MAAM,CAACgB,MAAMhB,MAAM,EAAEC,IAAI,CAACe,MAAMb,IAAI;YACxC;QACF;QACA,MAAMxB,eAAe2B,OAAO;YAAEY,KAAKN,OAAOM,GAAG;YAAEC,OAAOP,OAAOO,KAAK;QAAC,GAAGZ,QAAQ;YAC5EE,MAAMD,OAAOC,IAAI;WACbC,KAAK;YAAEA;QAAG,IAAI,CAAC,GACfC,OAAO;YAAEA;QAAK,IAAI,CAAC;QAEzBd,IAAIG,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEc,IAAI;QAAK;IAClC,EAAE,OAAOb,OAAO;QACdkB,QAAQlB,KAAK,CAAC,6BAA6BI,OAAOJ;QAClDL,IAAIG,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAmC;IACnE;AACF,EAAC;AAED,eAAeP,sBAAqB"}
@@ -0,0 +1,110 @@
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
+ * WHO IS CALLING AT THE ORGANIZATION LEVEL (AGL-2634).
19
+ *
20
+ * The CRM's host-routed actions — a stage move, a merge, an erasure, an
21
+ * email — were written for the site hub: each resolves the org FROM the
22
+ * site, checks the caller's role ON that site, and logs into that site's
23
+ * feed. The organization-level hub (AGL-2630) mounts the same surfaces with
24
+ * no site, and for a while every one of those actions ran "as the record's
25
+ * own capturing site", which left a record nobody's site had captured with
26
+ * nothing to run as. The org variant of each route authorizes HERE instead:
27
+ * by the org the body names, for an org-wide member, with the permission
28
+ * the whole CRM is gated on — the same three facts the org hub's own page
29
+ * gate checks (`resolveOrgCrmAccess`), so what the console offers and what
30
+ * the server admits cannot drift.
31
+ *
32
+ * A ROLE IS NOT A REACH. A site collaborator is a real member document
33
+ * carrying `role: 'editor'`, and that role holds `data.manage` — so a gate
34
+ * that read the permission alone would admit a contractor on one microsite
35
+ * to act over every site in the agency. `orgWide` is checked first and
36
+ * separately, and no permission grant restores it; this is the boundary the
37
+ * host variants get for free from the site role, spelled out for the variant
38
+ * that has no site.
39
+ */
40
+ import { type AglynOrganization, type PluginApiRequest } from '@aglyn/aglyn/server';
41
+ /**
42
+ * Which level a CRM route runs at, read off its body once.
43
+ *
44
+ * `orgId` present is the ORGANIZATION variant, whatever else the body
45
+ * carries: the org-level console always names its org, and a `hostId`
46
+ * beside it is the record's own site or the site an email leaves from —
47
+ * never what the caller is authorized against. `hostId` alone is the site
48
+ * variant every route has always had.
49
+ */
50
+ export interface CrmRouteScope {
51
+ level: 'site' | 'org';
52
+ hostId: string;
53
+ orgId: string;
54
+ }
55
+ export declare function readCrmRouteScope(body: Record<string, unknown> | null | undefined): CrmRouteScope | null;
56
+ /**
57
+ * Whether `uid` holds `data.manage` in `orgId`, as the permission catalog
58
+ * resolves it: the member's role, a custom role and per-member overrides
59
+ * (AGL-2843).
60
+ *
61
+ * Asked of `memberHasOrgPermission`, never of the `permissions` map
62
+ * `resolveOrgPermissions` returns. That map is the legacy six keys plus the
63
+ * keys plugins register (`ResolvedOrgPermissionSet`), and `data.manage` is a
64
+ * catalog key, so it is never in it: a gate that read it there would refuse
65
+ * everyone but staff. A lookup that fails answers `false`.
66
+ */
67
+ export declare function holdsDataManage(orgId: string | null | undefined, uid: string): Promise<boolean>;
68
+ export interface OrgCaller {
69
+ ok: true;
70
+ uid: string;
71
+ /** The token's address, or null for an account with none. */
72
+ email: string | null;
73
+ /** The token's display name, `''` when it carries none. */
74
+ name: string;
75
+ staff: boolean;
76
+ orgId: string;
77
+ org: Partial<AglynOrganization>;
78
+ }
79
+ export interface OrgCallerRefusal {
80
+ ok: false;
81
+ status: number;
82
+ error: string;
83
+ }
84
+ /** What the caller must hold over the whole organization. */
85
+ export type OrgCallerRequirement =
86
+ /** `data.manage`, org-wide — the key the CRM is gated on. Staff pass. */
87
+ 'data.manage'
88
+ /** A workspace owner or admin, org-wide. Staff acting alone do NOT pass. */
89
+ | 'manage-org';
90
+ /**
91
+ * A verified session, org-wide reach in `orgId`, and the requirement — in
92
+ * that order, the cheapest refusal first — then the org document, which
93
+ * every org variant needs for the plan and the consent groups.
94
+ *
95
+ * Staff are admitted to the `data.manage` requirement as every CRM route
96
+ * admits them, and refused the `manage-org` one as the erasure route
97
+ * refuses them: the workspace is the controller of its people's data and
98
+ * the instruction to erase has to come from it.
99
+ */
100
+ export declare function authorizeOrgCaller(req: PluginApiRequest, orgId: string, options: {
101
+ needs: OrgCallerRequirement;
102
+ refusal: string;
103
+ }): Promise<OrgCaller | OrgCallerRefusal>;
104
+ /**
105
+ * Every site of the organization, by document id — the host set an
106
+ * org-level act sweeps when it needs one (AGL-2634). One equality on
107
+ * `hosts.orgId`, the query the erasure route already ran, which needs no
108
+ * composite index.
109
+ */
110
+ export declare function orgHostIds(firestore: FirebaseFirestore.Firestore, orgId: string): Promise<string[]>;
@@ -0,0 +1,154 @@
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
+ * WHO IS CALLING AT THE ORGANIZATION LEVEL (AGL-2634).
18
+ *
19
+ * The CRM's host-routed actions — a stage move, a merge, an erasure, an
20
+ * email — were written for the site hub: each resolves the org FROM the
21
+ * site, checks the caller's role ON that site, and logs into that site's
22
+ * feed. The organization-level hub (AGL-2630) mounts the same surfaces with
23
+ * no site, and for a while every one of those actions ran "as the record's
24
+ * own capturing site", which left a record nobody's site had captured with
25
+ * nothing to run as. The org variant of each route authorizes HERE instead:
26
+ * by the org the body names, for an org-wide member, with the permission
27
+ * the whole CRM is gated on — the same three facts the org hub's own page
28
+ * gate checks (`resolveOrgCrmAccess`), so what the console offers and what
29
+ * the server admits cannot drift.
30
+ *
31
+ * A ROLE IS NOT A REACH. A site collaborator is a real member document
32
+ * carrying `role: 'editor'`, and that role holds `data.manage` — so a gate
33
+ * that read the permission alone would admit a contractor on one microsite
34
+ * to act over every site in the agency. `orgWide` is checked first and
35
+ * separately, and no permission grant restores it; this is the boundary the
36
+ * host variants get for free from the site role, spelled out for the variant
37
+ * that has no site.
38
+ */ import { canManageOrg } from "@aglyn/aglyn/server";
39
+ import { firebaseAdmin, getOrgDoc, memberHasOrgPermission, resolveOrgMembership } from "@aglyn/tenant-data-admin";
40
+ import { isRefusedIdToken } from "@aglyn/tenant-data-admin/server/id-token-refusal";
41
+ import { resolveOrgPermissions } from "@aglyn/tenant-runtime/org-permissions";
42
+ export function readCrmRouteScope(body) {
43
+ var _ref, _ref1;
44
+ const hostId = String((_ref = body == null ? void 0 : body['hostId']) != null ? _ref : '').trim().slice(0, 128);
45
+ const orgId = String((_ref1 = body == null ? void 0 : body['orgId']) != null ? _ref1 : '').trim().slice(0, 128);
46
+ if (orgId) return {
47
+ level: 'org',
48
+ hostId,
49
+ orgId
50
+ };
51
+ if (hostId) return {
52
+ level: 'site',
53
+ hostId,
54
+ orgId: ''
55
+ };
56
+ return null;
57
+ }
58
+ /**
59
+ * Whether `uid` holds `data.manage` in `orgId`, as the permission catalog
60
+ * resolves it: the member's role, a custom role and per-member overrides
61
+ * (AGL-2843).
62
+ *
63
+ * Asked of `memberHasOrgPermission`, never of the `permissions` map
64
+ * `resolveOrgPermissions` returns. That map is the legacy six keys plus the
65
+ * keys plugins register (`ResolvedOrgPermissionSet`), and `data.manage` is a
66
+ * catalog key, so it is never in it: a gate that read it there would refuse
67
+ * everyone but staff. A lookup that fails answers `false`.
68
+ */ export async function holdsDataManage(orgId, uid) {
69
+ if (!orgId) return false;
70
+ try {
71
+ var _ref;
72
+ const membership = await resolveOrgMembership(uid, orgId);
73
+ const member = (_ref = membership == null ? void 0 : membership.member) != null ? _ref : null;
74
+ if (!member) return false;
75
+ return await memberHasOrgPermission(orgId, member, 'data.manage') === true;
76
+ } catch (unused) {
77
+ return false;
78
+ }
79
+ }
80
+ /**
81
+ * A verified session, org-wide reach in `orgId`, and the requirement — in
82
+ * that order, the cheapest refusal first — then the org document, which
83
+ * every org variant needs for the plan and the consent groups.
84
+ *
85
+ * Staff are admitted to the `data.manage` requirement as every CRM route
86
+ * admits them, and refused the `manage-org` one as the erasure route
87
+ * refuses them: the workspace is the controller of its people's data and
88
+ * the instruction to erase has to come from it.
89
+ */ export async function authorizeOrgCaller(req, orgId, options) {
90
+ var _req_headers_authorization, _ref, _decoded_email, _decoded_name;
91
+ const authorization = String((_req_headers_authorization = req.headers.authorization) != null ? _req_headers_authorization : '');
92
+ const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined;
93
+ if (!idToken) return {
94
+ ok: false,
95
+ status: 401,
96
+ error: 'Unauthenticated'
97
+ };
98
+ let decoded;
99
+ try {
100
+ decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken);
101
+ } catch (error) {
102
+ // A refused credential is the caller's 401. A failure to check one is
103
+ // ours and keeps a 5xx, so an outage pages instead of reading as a bad
104
+ // token (AGL-2852).
105
+ if (isRefusedIdToken(error)) return {
106
+ ok: false,
107
+ status: 401,
108
+ error: 'Unauthenticated'
109
+ };
110
+ console.error('[crm] the organization caller could not be verified', error);
111
+ return {
112
+ ok: false,
113
+ status: 500,
114
+ error: 'The sign-in could not be checked. Try again.'
115
+ };
116
+ }
117
+ const staff = decoded.staff === true;
118
+ const membership = await resolveOrgPermissions(decoded.uid, {
119
+ orgId
120
+ }).catch(()=>null);
121
+ const orgWide = Boolean(membership == null ? void 0 : membership.orgWide) && (membership == null ? void 0 : membership.orgId) === orgId;
122
+ const admitted = options.needs === 'data.manage' ? staff || orgWide && await holdsDataManage(orgId, decoded.uid) : orgWide && canManageOrg((_ref = membership == null ? void 0 : membership.role) != null ? _ref : null);
123
+ if (!admitted) return {
124
+ ok: false,
125
+ status: 403,
126
+ error: options.refusal
127
+ };
128
+ const org = await getOrgDoc(orgId).catch(()=>null);
129
+ if (!org) return {
130
+ ok: false,
131
+ status: 404,
132
+ error: 'Unknown organization'
133
+ };
134
+ return {
135
+ ok: true,
136
+ uid: decoded.uid,
137
+ email: (_decoded_email = decoded.email) != null ? _decoded_email : null,
138
+ name: String((_decoded_name = decoded.name) != null ? _decoded_name : '').trim().slice(0, 120),
139
+ staff,
140
+ orgId,
141
+ org
142
+ };
143
+ }
144
+ /**
145
+ * Every site of the organization, by document id — the host set an
146
+ * org-level act sweeps when it needs one (AGL-2634). One equality on
147
+ * `hosts.orgId`, the query the erasure route already ran, which needs no
148
+ * composite index.
149
+ */ export async function orgHostIds(firestore, orgId) {
150
+ const hosts = await firestore.collection('hosts').where('orgId', '==', orgId).get();
151
+ return hosts.docs.map((doc)=>String(doc.id));
152
+ }
153
+
154
+ //# sourceMappingURL=org-caller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/server/org-caller.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 * WHO IS CALLING AT THE ORGANIZATION LEVEL (AGL-2634).\n *\n * The CRM's host-routed actions — a stage move, a merge, an erasure, an\n * email — were written for the site hub: each resolves the org FROM the\n * site, checks the caller's role ON that site, and logs into that site's\n * feed. The organization-level hub (AGL-2630) mounts the same surfaces with\n * no site, and for a while every one of those actions ran \"as the record's\n * own capturing site\", which left a record nobody's site had captured with\n * nothing to run as. The org variant of each route authorizes HERE instead:\n * by the org the body names, for an org-wide member, with the permission\n * the whole CRM is gated on — the same three facts the org hub's own page\n * gate checks (`resolveOrgCrmAccess`), so what the console offers and what\n * the server admits cannot drift.\n *\n * A ROLE IS NOT A REACH. A site collaborator is a real member document\n * carrying `role: 'editor'`, and that role holds `data.manage` — so a gate\n * that read the permission alone would admit a contractor on one microsite\n * to act over every site in the agency. `orgWide` is checked first and\n * separately, and no permission grant restores it; this is the boundary the\n * host variants get for free from the site role, spelled out for the variant\n * that has no site.\n */\n\nimport { type AglynOrganization, canManageOrg, type PluginApiRequest } from '@aglyn/aglyn/server'\nimport {\n firebaseAdmin,\n getOrgDoc,\n memberHasOrgPermission,\n resolveOrgMembership,\n} from '@aglyn/tenant-data-admin'\nimport { isRefusedIdToken } from '@aglyn/tenant-data-admin/server/id-token-refusal'\nimport { resolveOrgPermissions } from '@aglyn/tenant-runtime/org-permissions'\n\n/**\n * Which level a CRM route runs at, read off its body once.\n *\n * `orgId` present is the ORGANIZATION variant, whatever else the body\n * carries: the org-level console always names its org, and a `hostId`\n * beside it is the record's own site or the site an email leaves from —\n * never what the caller is authorized against. `hostId` alone is the site\n * variant every route has always had.\n */\nexport interface CrmRouteScope {\n level: 'site' | 'org'\n hostId: string\n orgId: string\n}\n\nexport function readCrmRouteScope(\n body: Record<string, unknown> | null | undefined,\n): CrmRouteScope | null {\n const hostId = String(body?.['hostId'] ?? '')\n .trim()\n .slice(0, 128)\n const orgId = String(body?.['orgId'] ?? '')\n .trim()\n .slice(0, 128)\n if (orgId) return { level: 'org', hostId, orgId }\n if (hostId) return { level: 'site', hostId, orgId: '' }\n return null\n}\n\n/**\n * Whether `uid` holds `data.manage` in `orgId`, as the permission catalog\n * resolves it: the member's role, a custom role and per-member overrides\n * (AGL-2843).\n *\n * Asked of `memberHasOrgPermission`, never of the `permissions` map\n * `resolveOrgPermissions` returns. That map is the legacy six keys plus the\n * keys plugins register (`ResolvedOrgPermissionSet`), and `data.manage` is a\n * catalog key, so it is never in it: a gate that read it there would refuse\n * everyone but staff. A lookup that fails answers `false`.\n */\nexport async function holdsDataManage(\n orgId: string | null | undefined,\n uid: string,\n): Promise<boolean> {\n if (!orgId) return false\n try {\n const membership = await resolveOrgMembership(uid, orgId)\n const member = membership?.member ?? null\n if (!member) return false\n return (await memberHasOrgPermission(orgId, member, 'data.manage')) === true\n } catch {\n return false\n }\n}\n\nexport interface OrgCaller {\n ok: true\n uid: string\n /** The token's address, or null for an account with none. */\n email: string | null\n /** The token's display name, `''` when it carries none. */\n name: string\n staff: boolean\n orgId: string\n org: Partial<AglynOrganization>\n}\n\nexport interface OrgCallerRefusal {\n ok: false\n status: number\n error: string\n}\n\n/** What the caller must hold over the whole organization. */\nexport type OrgCallerRequirement =\n /** `data.manage`, org-wide — the key the CRM is gated on. Staff pass. */\n | 'data.manage'\n /** A workspace owner or admin, org-wide. Staff acting alone do NOT pass. */\n | 'manage-org'\n\n/**\n * A verified session, org-wide reach in `orgId`, and the requirement — in\n * that order, the cheapest refusal first — then the org document, which\n * every org variant needs for the plan and the consent groups.\n *\n * Staff are admitted to the `data.manage` requirement as every CRM route\n * admits them, and refused the `manage-org` one as the erasure route\n * refuses them: the workspace is the controller of its people's data and\n * the instruction to erase has to come from it.\n */\nexport async function authorizeOrgCaller(\n req: PluginApiRequest,\n orgId: string,\n options: { needs: OrgCallerRequirement; refusal: string },\n): Promise<OrgCaller | OrgCallerRefusal> {\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ')\n ? authorization.slice('Bearer '.length)\n : undefined\n if (!idToken) return { ok: false, status: 401, error: 'Unauthenticated' }\n let decoded: { uid: string; email?: string; name?: string; staff?: unknown }\n try {\n decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n } catch (error) {\n // A refused credential is the caller's 401. A failure to check one is\n // ours and keeps a 5xx, so an outage pages instead of reading as a bad\n // token (AGL-2852).\n if (isRefusedIdToken(error)) return { ok: false, status: 401, error: 'Unauthenticated' }\n console.error('[crm] the organization caller could not be verified', error)\n return { ok: false, status: 500, error: 'The sign-in could not be checked. Try again.' }\n }\n const staff = decoded.staff === true\n const membership = await resolveOrgPermissions(decoded.uid, { orgId }).catch(\n () => null,\n )\n const orgWide = Boolean(membership?.orgWide) && membership?.orgId === orgId\n const admitted =\n options.needs === 'data.manage'\n ? staff || (orgWide && (await holdsDataManage(orgId, decoded.uid)))\n : orgWide && canManageOrg(membership?.role ?? null)\n if (!admitted) return { ok: false, status: 403, error: options.refusal }\n const org = await getOrgDoc(orgId).catch(() => null)\n if (!org) return { ok: false, status: 404, error: 'Unknown organization' }\n return {\n ok: true,\n uid: decoded.uid,\n email: decoded.email ?? null,\n name: String(decoded.name ?? '')\n .trim()\n .slice(0, 120),\n staff,\n orgId,\n org,\n }\n}\n\n/**\n * Every site of the organization, by document id — the host set an\n * org-level act sweeps when it needs one (AGL-2634). One equality on\n * `hosts.orgId`, the query the erasure route already ran, which needs no\n * composite index.\n */\nexport async function orgHostIds(\n firestore: FirebaseFirestore.Firestore,\n orgId: string,\n): Promise<string[]> {\n const hosts = await firestore.collection('hosts').where('orgId', '==', orgId).get()\n return hosts.docs.map((doc: { id: string }) => String(doc.id))\n}\n"],"names":["canManageOrg","firebaseAdmin","getOrgDoc","memberHasOrgPermission","resolveOrgMembership","isRefusedIdToken","resolveOrgPermissions","readCrmRouteScope","body","hostId","String","trim","slice","orgId","level","holdsDataManage","uid","membership","member","authorizeOrgCaller","req","options","decoded","authorization","headers","idToken","startsWith","length","undefined","ok","status","error","app","auth","verifyIdToken","console","staff","catch","orgWide","Boolean","admitted","needs","role","refusal","org","email","name","orgHostIds","firestore","hosts","collection","where","get","docs","map","doc","id"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;CAsBC,GAED,SAAiCA,YAAY,QAA+B,sBAAqB;AACjG,SACEC,aAAa,EACbC,SAAS,EACTC,sBAAsB,EACtBC,oBAAoB,QACf,2BAA0B;AACjC,SAASC,gBAAgB,QAAQ,mDAAkD;AACnF,SAASC,qBAAqB,QAAQ,wCAAuC;AAiB7E,OAAO,SAASC,kBACdC,IAAgD;;IAEhD,MAAMC,SAASC,eAAOF,wBAAAA,IAAM,CAAC,SAAS,mBAAI,IACvCG,IAAI,GACJC,KAAK,CAAC,GAAG;IACZ,MAAMC,QAAQH,gBAAOF,wBAAAA,IAAM,CAAC,QAAQ,oBAAI,IACrCG,IAAI,GACJC,KAAK,CAAC,GAAG;IACZ,IAAIC,OAAO,OAAO;QAAEC,OAAO;QAAOL;QAAQI;IAAM;IAChD,IAAIJ,QAAQ,OAAO;QAAEK,OAAO;QAAQL;QAAQI,OAAO;IAAG;IACtD,OAAO;AACT;AAEA;;;;;;;;;;CAUC,GACD,OAAO,eAAeE,gBACpBF,KAAgC,EAChCG,GAAW;IAEX,IAAI,CAACH,OAAO,OAAO;IACnB,IAAI;;QACF,MAAMI,aAAa,MAAMb,qBAAqBY,KAAKH;QACnD,MAAMK,iBAASD,8BAAAA,WAAYC,MAAM,mBAAI;QACrC,IAAI,CAACA,QAAQ,OAAO;QACpB,OAAO,AAAC,MAAMf,uBAAuBU,OAAOK,QAAQ,mBAAoB;IAC1E,EAAE,eAAM;QACN,OAAO;IACT;AACF;AA2BA;;;;;;;;;CASC,GACD,OAAO,eAAeC,mBACpBC,GAAqB,EACrBP,KAAa,EACbQ,OAAyD;QAE5BD,kCA+BpBE,gBACMA;IAhCf,MAAMC,gBAAgBb,QAAOU,6BAAAA,IAAII,OAAO,CAACD,aAAa,YAAzBH,6BAA6B;IAC1D,MAAMK,UAAUF,cAAcG,UAAU,CAAC,aACrCH,cAAcX,KAAK,CAAC,UAAUe,MAAM,IACpCC;IACJ,IAAI,CAACH,SAAS,OAAO;QAAEI,IAAI;QAAOC,QAAQ;QAAKC,OAAO;IAAkB;IACxE,IAAIT;IACJ,IAAI;QACFA,UAAU,MAAMrB,cAAc+B,GAAG,GAAGC,IAAI,GAAGC,aAAa,CAACT;IAC3D,EAAE,OAAOM,OAAO;QACd,sEAAsE;QACtE,uEAAuE;QACvE,oBAAoB;QACpB,IAAI1B,iBAAiB0B,QAAQ,OAAO;YAAEF,IAAI;YAAOC,QAAQ;YAAKC,OAAO;QAAkB;QACvFI,QAAQJ,KAAK,CAAC,uDAAuDA;QACrE,OAAO;YAAEF,IAAI;YAAOC,QAAQ;YAAKC,OAAO;QAA+C;IACzF;IACA,MAAMK,QAAQd,QAAQc,KAAK,KAAK;IAChC,MAAMnB,aAAa,MAAMX,sBAAsBgB,QAAQN,GAAG,EAAE;QAAEH;IAAM,GAAGwB,KAAK,CAC1E,IAAM;IAER,MAAMC,UAAUC,QAAQtB,8BAAAA,WAAYqB,OAAO,KAAKrB,CAAAA,8BAAAA,WAAYJ,KAAK,MAAKA;IACtE,MAAM2B,WACJnB,QAAQoB,KAAK,KAAK,gBACdL,SAAUE,WAAY,MAAMvB,gBAAgBF,OAAOS,QAAQN,GAAG,IAC9DsB,WAAWtC,qBAAaiB,8BAAAA,WAAYyB,IAAI,mBAAI;IAClD,IAAI,CAACF,UAAU,OAAO;QAAEX,IAAI;QAAOC,QAAQ;QAAKC,OAAOV,QAAQsB,OAAO;IAAC;IACvE,MAAMC,MAAM,MAAM1C,UAAUW,OAAOwB,KAAK,CAAC,IAAM;IAC/C,IAAI,CAACO,KAAK,OAAO;QAAEf,IAAI;QAAOC,QAAQ;QAAKC,OAAO;IAAuB;IACzE,OAAO;QACLF,IAAI;QACJb,KAAKM,QAAQN,GAAG;QAChB6B,KAAK,GAAEvB,iBAAAA,QAAQuB,KAAK,YAAbvB,iBAAiB;QACxBwB,MAAMpC,QAAOY,gBAAAA,QAAQwB,IAAI,YAAZxB,gBAAgB,IAC1BX,IAAI,GACJC,KAAK,CAAC,GAAG;QACZwB;QACAvB;QACA+B;IACF;AACF;AAEA;;;;;CAKC,GACD,OAAO,eAAeG,WACpBC,SAAsC,EACtCnC,KAAa;IAEb,MAAMoC,QAAQ,MAAMD,UAAUE,UAAU,CAAC,SAASC,KAAK,CAAC,SAAS,MAAMtC,OAAOuC,GAAG;IACjF,OAAOH,MAAMI,IAAI,CAACC,GAAG,CAAC,CAACC,MAAwB7C,OAAO6C,IAAIC,EAAE;AAC9D"}
@@ -0,0 +1,75 @@
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 RECIPES, INSTALLED FROM THE ORGANIZATION (AGL-2639).
19
+ *
20
+ * On a site, a recipe opens the Actions editor prefilled and writes nothing
21
+ * until the person saves — the editor is the writer, and the site's own
22
+ * role is the authority. The organization-level CRM hub has no editor: it
23
+ * mounts over every site with no site of its own, and an org running five
24
+ * sites installed "Welcome a new lead" five times by hand. These two routes
25
+ * are the org hub's door to a site's automations.
26
+ *
27
+ * `crm/recipe-install` writes the action a recipe builds into ONE site's
28
+ * `hosts/{hostId}/actions`, as the site editor would have saved it — the
29
+ * same builder, the same validator, the same stored shape — and refuses a
30
+ * second install of the same recipe on the same site by the stamp the
31
+ * builder puts on it. A server route rather than a client write for three
32
+ * reasons the browser cannot supply: the document is created by a server
33
+ * on every plan (the rules close `actions` to client creates, and the
34
+ * per-site cap is counted here); the stamp is the server's word, not the
35
+ * caller's; and the site is checked to be one the caller may manage —
36
+ * at the org level, a site OF THE ORG the caller holds org-wide reach in,
37
+ * so a host id typed into the body cannot reach a site under another
38
+ * workspace.
39
+ *
40
+ * `crm/recipe-status` reads the stamps back for every site of the org, so
41
+ * the card can say which sites carry which recipe. An action with no stamp
42
+ * at all — saved before the stamp existed — is counted, not ignored: it
43
+ * may well be a recipe, and the reader is told the site "may already have
44
+ * it" rather than shown a clean slate.
45
+ *
46
+ * Both routes serve the site variant too (`hostId` alone, authorized by the
47
+ * host role that creates actions today), so a site-level caller gets the
48
+ * same answers; the org variant (`orgId` in the body) is the one the org
49
+ * hub uses.
50
+ */
51
+ import { type PluginApiHandler } from '@aglyn/aglyn/server';
52
+ export declare const CRM_RECIPE_INSTALL_ROUTE: "crm/recipe-install";
53
+ export declare const CRM_RECIPE_STATUS_ROUTE: "crm/recipe-status";
54
+ /**
55
+ * `POST /api/crm/recipe-install`
56
+ *
57
+ * The body is a CrmRecipeInstallRequest: the site, the recipe, the form a
58
+ * recipe that needs one is keyed on, and the org at the organization level.
59
+ * Answers 201 with a CrmRecipeInstallResult once the action is written, and
60
+ * 409 when a live action on the site already carries the stamp — naming it,
61
+ * so the caller can say "already installed" rather than install it twice.
62
+ *
63
+ * The write is one transaction: the stamps are read, the duplicate and the
64
+ * per-site cap are judged, and the document is created — all inside it, so
65
+ * two installs racing for the same site cannot both land.
66
+ */
67
+ export declare const crmRecipeInstallHandler: PluginApiHandler;
68
+ /**
69
+ * `POST /api/crm/recipe-status`
70
+ *
71
+ * The body names the organization (`orgId`) for every one of its sites, or
72
+ * one site (`hostId`) for that site alone. Answers `ok: true` and `sites`,
73
+ * one CrmRecipeSiteStatus per site swept.
74
+ */
75
+ export declare const crmRecipeStatusHandler: PluginApiHandler;