@aglyn/aglyn 1.0.0-beta.220 → 1.0.0-beta.222

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 (358) hide show
  1. package/package.json +15 -11
  2. package/src/lib/app-utils/agent-openapi.js +1 -1
  3. package/src/lib/app-utils/agent-openapi.js.map +1 -1
  4. package/src/lib/app-utils/analytics-events.d.ts +3 -2
  5. package/src/lib/app-utils/analytics-events.js +3 -2
  6. package/src/lib/app-utils/analytics-events.js.map +1 -1
  7. package/src/lib/app-utils/api-plugins.d.ts +30 -0
  8. package/src/lib/app-utils/api-plugins.js +24 -1
  9. package/src/lib/app-utils/api-plugins.js.map +1 -1
  10. package/src/lib/app-utils/author-html.d.ts +1 -1
  11. package/src/lib/app-utils/author-html.js.map +1 -1
  12. package/src/lib/app-utils/bandwidth-cap.d.ts +12 -1
  13. package/src/lib/app-utils/bandwidth-cap.js +17 -1
  14. package/src/lib/app-utils/bandwidth-cap.js.map +1 -1
  15. package/src/lib/app-utils/compose-reusable-components.d.ts +19 -0
  16. package/src/lib/app-utils/compose-reusable-components.js +116 -26
  17. package/src/lib/app-utils/compose-reusable-components.js.map +1 -1
  18. package/src/lib/app-utils/console-routes.d.ts +4 -0
  19. package/src/lib/app-utils/console-routes.js +3 -0
  20. package/src/lib/app-utils/console-routes.js.map +1 -1
  21. package/src/lib/app-utils/contacts.d.ts +71 -0
  22. package/src/lib/app-utils/contacts.js +55 -0
  23. package/src/lib/app-utils/contacts.js.map +1 -1
  24. package/src/lib/app-utils/contexts.d.ts +1 -0
  25. package/src/lib/app-utils/contexts.js +1 -0
  26. package/src/lib/app-utils/contexts.js.map +1 -1
  27. package/src/lib/app-utils/crm-email-templates.js +21 -4
  28. package/src/lib/app-utils/crm-email-templates.js.map +1 -1
  29. package/src/lib/app-utils/crm-kinds.d.ts +2 -0
  30. package/src/lib/app-utils/crm-kinds.js +1 -0
  31. package/src/lib/app-utils/crm-kinds.js.map +1 -1
  32. package/src/lib/app-utils/crm.d.ts +1199 -67
  33. package/src/lib/app-utils/crm.js +1951 -310
  34. package/src/lib/app-utils/crm.js.map +1 -1
  35. package/src/lib/app-utils/csv-import.d.ts +10 -38
  36. package/src/lib/app-utils/csv-import.js +17 -42
  37. package/src/lib/app-utils/csv-import.js.map +1 -1
  38. package/src/lib/app-utils/csv.d.ts +32 -11
  39. package/src/lib/app-utils/csv.js +43 -5
  40. package/src/lib/app-utils/csv.js.map +1 -1
  41. package/src/lib/app-utils/default-site.d.ts +116 -0
  42. package/src/lib/app-utils/default-site.js +1024 -0
  43. package/src/lib/app-utils/default-site.js.map +1 -0
  44. package/src/lib/app-utils/docs-help.generated.d.ts +23 -23
  45. package/src/lib/app-utils/docs-help.generated.js +47 -10
  46. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  47. package/src/lib/app-utils/docs-index.generated.js +746 -151
  48. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  49. package/src/lib/app-utils/draft-placeholders.d.ts +76 -0
  50. package/src/lib/app-utils/draft-placeholders.js +115 -0
  51. package/src/lib/app-utils/draft-placeholders.js.map +1 -0
  52. package/src/lib/app-utils/entity-picker-context.d.ts +19 -15
  53. package/src/lib/app-utils/entity-picker-context.js +4 -4
  54. package/src/lib/app-utils/entity-picker-context.js.map +1 -1
  55. package/src/lib/app-utils/expand-repeatables.d.ts +66 -10
  56. package/src/lib/app-utils/expand-repeatables.js +88 -14
  57. package/src/lib/app-utils/expand-repeatables.js.map +1 -1
  58. package/src/lib/app-utils/forms.d.ts +33 -22
  59. package/src/lib/app-utils/forms.js +47 -28
  60. package/src/lib/app-utils/forms.js.map +1 -1
  61. package/src/lib/app-utils/full-use-cost.d.ts +277 -0
  62. package/src/lib/app-utils/full-use-cost.js +421 -0
  63. package/src/lib/app-utils/full-use-cost.js.map +1 -0
  64. package/src/lib/app-utils/health-report.js +33 -0
  65. package/src/lib/app-utils/health-report.js.map +1 -1
  66. package/src/lib/app-utils/leaving-notice.d.ts +96 -0
  67. package/src/lib/app-utils/leaving-notice.js +157 -0
  68. package/src/lib/app-utils/leaving-notice.js.map +1 -0
  69. package/src/lib/app-utils/llms-txt.d.ts +20 -0
  70. package/src/lib/app-utils/llms-txt.js +7 -1
  71. package/src/lib/app-utils/llms-txt.js.map +1 -1
  72. package/src/lib/app-utils/media-asset-facts.d.ts +16 -1
  73. package/src/lib/app-utils/media-asset-facts.js +40 -13
  74. package/src/lib/app-utils/media-asset-facts.js.map +1 -1
  75. package/src/lib/app-utils/media-bandwidth.d.ts +52 -0
  76. package/src/lib/app-utils/media-bandwidth.js +94 -0
  77. package/src/lib/app-utils/media-bandwidth.js.map +1 -0
  78. package/src/lib/app-utils/media-ref.d.ts +241 -33
  79. package/src/lib/app-utils/media-ref.js +324 -43
  80. package/src/lib/app-utils/media-ref.js.map +1 -1
  81. package/src/lib/app-utils/media-src.d.ts +8 -8
  82. package/src/lib/app-utils/media-src.js +27 -11
  83. package/src/lib/app-utils/media-src.js.map +1 -1
  84. package/src/lib/app-utils/media-takedown-reach.d.ts +4 -1
  85. package/src/lib/app-utils/media-takedown-reach.js +6 -3
  86. package/src/lib/app-utils/media-takedown-reach.js.map +1 -1
  87. package/src/lib/app-utils/notifications.d.ts +1 -1
  88. package/src/lib/app-utils/notifications.js +2 -0
  89. package/src/lib/app-utils/notifications.js.map +1 -1
  90. package/src/lib/app-utils/operator-alerts.js +17 -0
  91. package/src/lib/app-utils/operator-alerts.js.map +1 -1
  92. package/src/lib/app-utils/organizations.d.ts +51 -2
  93. package/src/lib/app-utils/organizations.js +56 -3
  94. package/src/lib/app-utils/organizations.js.map +1 -1
  95. package/src/lib/app-utils/page-record-sources.d.ts +87 -0
  96. package/src/lib/app-utils/page-record-sources.js +53 -0
  97. package/src/lib/app-utils/page-record-sources.js.map +1 -0
  98. package/src/lib/app-utils/paid-media-source.d.ts +3 -7
  99. package/src/lib/app-utils/paid-media-source.js +5 -19
  100. package/src/lib/app-utils/paid-media-source.js.map +1 -1
  101. package/src/lib/app-utils/person-erasure.d.ts +5 -2
  102. package/src/lib/app-utils/person-erasure.js.map +1 -1
  103. package/src/lib/app-utils/picklists.d.ts +187 -0
  104. package/src/lib/app-utils/picklists.js +320 -0
  105. package/src/lib/app-utils/picklists.js.map +1 -0
  106. package/src/lib/app-utils/plan-entitlements.d.ts +220 -50
  107. package/src/lib/app-utils/plan-entitlements.js +309 -115
  108. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  109. package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
  110. package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
  111. package/src/lib/app-utils/release-flags.d.ts +1 -1
  112. package/src/lib/app-utils/release-flags.js +11 -0
  113. package/src/lib/app-utils/release-flags.js.map +1 -1
  114. package/src/lib/app-utils/rendered-widths.d.ts +121 -0
  115. package/src/lib/app-utils/rendered-widths.js +211 -0
  116. package/src/lib/app-utils/rendered-widths.js.map +1 -0
  117. package/src/lib/app-utils/repeat-sources.d.ts +2 -1
  118. package/src/lib/app-utils/repeat-sources.js.map +1 -1
  119. package/src/lib/app-utils/screen-link-context-value.d.ts +7 -0
  120. package/src/lib/app-utils/screen-link-context-value.js.map +1 -1
  121. package/src/lib/app-utils/screen-link-context.js +14 -2
  122. package/src/lib/app-utils/screen-link-context.js.map +1 -1
  123. package/src/lib/app-utils/screen-route.d.ts +157 -36
  124. package/src/lib/app-utils/screen-route.js +191 -41
  125. package/src/lib/app-utils/screen-route.js.map +1 -1
  126. package/src/lib/app-utils/seo-audit.d.ts +11 -1
  127. package/src/lib/app-utils/seo-audit.js +33 -13
  128. package/src/lib/app-utils/seo-audit.js.map +1 -1
  129. package/src/lib/app-utils/seo-keywords.d.ts +11 -0
  130. package/src/lib/app-utils/seo-keywords.js +19 -5
  131. package/src/lib/app-utils/seo-keywords.js.map +1 -1
  132. package/src/lib/app-utils/seo-page-facts.d.ts +47 -4
  133. package/src/lib/app-utils/seo-page-facts.js +136 -31
  134. package/src/lib/app-utils/seo-page-facts.js.map +1 -1
  135. package/src/lib/app-utils/seo-site-scan.d.ts +42 -4
  136. package/src/lib/app-utils/seo-site-scan.js +113 -12
  137. package/src/lib/app-utils/seo-site-scan.js.map +1 -1
  138. package/src/lib/app-utils/server.d.ts +5 -4
  139. package/src/lib/app-utils/server.js +14 -5
  140. package/src/lib/app-utils/server.js.map +1 -1
  141. package/src/lib/app-utils/site-icon-set.d.ts +195 -0
  142. package/src/lib/app-utils/site-icon-set.js +351 -0
  143. package/src/lib/app-utils/site-icon-set.js.map +1 -0
  144. package/src/lib/app-utils/site-interactions.d.ts +101 -4
  145. package/src/lib/app-utils/site-interactions.js +120 -4
  146. package/src/lib/app-utils/site-interactions.js.map +1 -1
  147. package/src/lib/app-utils/starter-template-nodes.d.ts +7 -0
  148. package/src/lib/app-utils/starter-template-nodes.js +3 -0
  149. package/src/lib/app-utils/starter-template-nodes.js.map +1 -1
  150. package/src/lib/app-utils/starter-templates.d.ts +5 -19
  151. package/src/lib/app-utils/starter-templates.js +5 -49
  152. package/src/lib/app-utils/starter-templates.js.map +1 -1
  153. package/src/lib/app-utils/transfer-launcher-context.d.ts +136 -0
  154. package/src/lib/app-utils/transfer-launcher-context.js +23 -0
  155. package/src/lib/app-utils/transfer-launcher-context.js.map +1 -0
  156. package/src/lib/app-utils/transfer-resume-import.d.ts +39 -0
  157. package/src/lib/app-utils/transfer-resume-import.js +128 -0
  158. package/src/lib/app-utils/transfer-resume-import.js.map +1 -0
  159. package/src/lib/app-utils/upgrade-proposal.d.ts +66 -0
  160. package/src/lib/app-utils/upgrade-proposal.js +95 -0
  161. package/src/lib/app-utils/upgrade-proposal.js.map +1 -0
  162. package/src/lib/app-utils/utc-month.d.ts +33 -0
  163. package/src/lib/app-utils/utc-month.js +35 -0
  164. package/src/lib/app-utils/utc-month.js.map +1 -0
  165. package/src/lib/app-utils/visitor-record-ceiling.d.ts +4 -4
  166. package/src/lib/app-utils/visitor-record-ceiling.js +4 -4
  167. package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
  168. package/src/lib/app-utils/wire-nodes.d.ts +39 -19
  169. package/src/lib/app-utils/wire-nodes.js +120 -34
  170. package/src/lib/app-utils/wire-nodes.js.map +1 -1
  171. package/src/lib/data-transfer/access.d.ts +74 -0
  172. package/src/lib/data-transfer/access.js +93 -0
  173. package/src/lib/data-transfer/access.js.map +1 -0
  174. package/src/lib/data-transfer/derive.d.ts +246 -0
  175. package/src/lib/data-transfer/derive.js +1007 -0
  176. package/src/lib/data-transfer/derive.js.map +1 -0
  177. package/src/lib/data-transfer/export-file.d.ts +46 -0
  178. package/src/lib/data-transfer/export-file.js +146 -0
  179. package/src/lib/data-transfer/export-file.js.map +1 -0
  180. package/src/lib/data-transfer/field-catalog.d.ts +134 -0
  181. package/src/lib/data-transfer/field-catalog.js +278 -0
  182. package/src/lib/data-transfer/field-catalog.js.map +1 -0
  183. package/src/lib/data-transfer/header-match.d.ts +129 -0
  184. package/src/lib/data-transfer/header-match.js +367 -0
  185. package/src/lib/data-transfer/header-match.js.map +1 -0
  186. package/src/lib/data-transfer/index.d.ts +34 -0
  187. package/src/lib/data-transfer/index.js +40 -0
  188. package/src/lib/data-transfer/index.js.map +1 -0
  189. package/src/lib/data-transfer/job.d.ts +190 -0
  190. package/src/lib/data-transfer/job.js +229 -0
  191. package/src/lib/data-transfer/job.js.map +1 -0
  192. package/src/lib/data-transfer/lookup.d.ts +45 -0
  193. package/src/lib/data-transfer/lookup.js +71 -0
  194. package/src/lib/data-transfer/lookup.js.map +1 -0
  195. package/src/lib/data-transfer/match.d.ts +99 -0
  196. package/src/lib/data-transfer/match.js +244 -0
  197. package/src/lib/data-transfer/match.js.map +1 -0
  198. package/src/lib/data-transfer/package-plan.d.ts +205 -0
  199. package/src/lib/data-transfer/package-plan.js +475 -0
  200. package/src/lib/data-transfer/package-plan.js.map +1 -0
  201. package/src/lib/data-transfer/package.d.ts +181 -0
  202. package/src/lib/data-transfer/package.js +426 -0
  203. package/src/lib/data-transfer/package.js.map +1 -0
  204. package/src/lib/data-transfer/picklist-map.d.ts +139 -0
  205. package/src/lib/data-transfer/picklist-map.js +271 -0
  206. package/src/lib/data-transfer/picklist-map.js.map +1 -0
  207. package/src/lib/data-transfer/plan.d.ts +176 -0
  208. package/src/lib/data-transfer/plan.js +451 -0
  209. package/src/lib/data-transfer/plan.js.map +1 -0
  210. package/src/lib/data-transfer/policy.d.ts +170 -0
  211. package/src/lib/data-transfer/policy.js +378 -0
  212. package/src/lib/data-transfer/policy.js.map +1 -0
  213. package/src/lib/data-transfer/resource.d.ts +211 -0
  214. package/src/lib/data-transfer/resource.js +241 -0
  215. package/src/lib/data-transfer/resource.js.map +1 -0
  216. package/src/lib/data-transfer/review.d.ts +70 -0
  217. package/src/lib/data-transfer/review.js +233 -0
  218. package/src/lib/data-transfer/review.js.map +1 -0
  219. package/src/lib/data-transfer/similarity.d.ts +40 -0
  220. package/src/lib/data-transfer/similarity.js +106 -0
  221. package/src/lib/data-transfer/similarity.js.map +1 -0
  222. package/src/lib/data-transfer/site-package.d.ts +365 -0
  223. package/src/lib/data-transfer/site-package.js +1077 -0
  224. package/src/lib/data-transfer/site-package.js.map +1 -0
  225. package/src/lib/data-transfer/source.d.ts +74 -0
  226. package/src/lib/data-transfer/source.js +293 -0
  227. package/src/lib/data-transfer/source.js.map +1 -0
  228. package/src/lib/data-transfer/transfer-api.d.ts +898 -0
  229. package/src/lib/data-transfer/transfer-api.js +107 -0
  230. package/src/lib/data-transfer/transfer-api.js.map +1 -0
  231. package/src/lib/foundation/definitions/org-billing.types.d.ts +31 -0
  232. package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
  233. package/src/lib/foundation/definitions/organization.types.d.ts +42 -1
  234. package/src/lib/foundation/definitions/organization.types.js.map +1 -1
  235. package/src/lib/foundation/definitions/platform.types.d.ts +6 -4
  236. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  237. package/src/lib/foundation/index.d.ts +1 -1
  238. package/src/lib/foundation/index.js.map +1 -1
  239. package/src/lib/plugin-manager/feature-plugins.d.ts +91 -2
  240. package/src/lib/plugin-manager/feature-plugins.js +48 -3
  241. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  242. package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +56 -0
  243. package/src/lib/plugin-manager/first-party-plugins.generated.js +1132 -27
  244. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  245. package/src/lib/plugin-manager/index.d.ts +0 -1
  246. package/src/lib/plugin-manager/index.js +0 -1
  247. package/src/lib/plugin-manager/index.js.map +1 -1
  248. package/src/lib/plugin-manager/interaction-recipes.d.ts +142 -0
  249. package/src/lib/plugin-manager/interaction-recipes.js +104 -0
  250. package/src/lib/plugin-manager/interaction-recipes.js.map +1 -0
  251. package/src/lib/plugin-manager/interaction-step-checks.d.ts +66 -0
  252. package/src/lib/plugin-manager/interaction-step-checks.js +86 -0
  253. package/src/lib/plugin-manager/interaction-step-checks.js.map +1 -0
  254. package/src/lib/plugin-manager/plugin-artifact-types.d.ts +235 -0
  255. package/src/lib/plugin-manager/plugin-artifact-types.js +99 -0
  256. package/src/lib/plugin-manager/plugin-artifact-types.js.map +1 -0
  257. package/src/lib/plugin-manager/plugin-contact-capture.d.ts +8 -0
  258. package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
  259. package/src/lib/plugin-manager/plugin-conversion-credit.d.ts +216 -0
  260. package/src/lib/plugin-manager/plugin-conversion-credit.js +91 -0
  261. package/src/lib/plugin-manager/plugin-conversion-credit.js.map +1 -0
  262. package/src/lib/plugin-manager/plugin-entity-pickers.d.ts +83 -0
  263. package/src/lib/plugin-manager/plugin-entity-pickers.js +87 -0
  264. package/src/lib/plugin-manager/plugin-entity-pickers.js.map +1 -0
  265. package/src/lib/plugin-manager/plugin-host-resources.d.ts +6 -0
  266. package/src/lib/plugin-manager/plugin-host-resources.js +6 -1
  267. package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -1
  268. package/src/lib/plugin-manager/plugin-intake-gates.d.ts +75 -0
  269. package/src/lib/plugin-manager/plugin-intake-gates.js +49 -0
  270. package/src/lib/plugin-manager/plugin-intake-gates.js.map +1 -0
  271. package/src/lib/plugin-manager/plugin-jobs.d.ts +5 -5
  272. package/src/lib/plugin-manager/plugin-jobs.js +7 -7
  273. package/src/lib/plugin-manager/plugin-jobs.js.map +1 -1
  274. package/src/lib/plugin-manager/plugin-live-paths.d.ts +70 -0
  275. package/src/lib/plugin-manager/plugin-live-paths.js +66 -0
  276. package/src/lib/plugin-manager/plugin-live-paths.js.map +1 -0
  277. package/src/lib/plugin-manager/plugin-org-erasure.d.ts +3 -2
  278. package/src/lib/plugin-manager/plugin-org-erasure.js +30 -5
  279. package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
  280. package/src/lib/plugin-manager/plugin-person-erasure.d.ts +68 -9
  281. package/src/lib/plugin-manager/plugin-person-erasure.js +196 -51
  282. package/src/lib/plugin-manager/plugin-person-erasure.js.map +1 -1
  283. package/src/lib/plugin-manager/plugin-person-records.d.ts +275 -0
  284. package/src/lib/plugin-manager/plugin-person-records.js +107 -0
  285. package/src/lib/plugin-manager/plugin-person-records.js.map +1 -0
  286. package/src/lib/plugin-manager/plugin-record-counts.d.ts +76 -0
  287. package/src/lib/plugin-manager/plugin-record-counts.js +49 -0
  288. package/src/lib/plugin-manager/plugin-record-counts.js.map +1 -0
  289. package/src/lib/plugin-manager/plugin-record-email-state.d.ts +26 -0
  290. package/src/lib/plugin-manager/plugin-record-email-state.js +16 -0
  291. package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
  292. package/src/lib/plugin-manager/plugin-record-index.d.ts +10 -0
  293. package/src/lib/plugin-manager/plugin-record-index.js.map +1 -1
  294. package/src/lib/plugin-manager/plugin-record-lists.d.ts +86 -6
  295. package/src/lib/plugin-manager/plugin-record-lists.js +42 -5
  296. package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -1
  297. package/src/lib/plugin-manager/plugin-record-origin.d.ts +79 -0
  298. package/src/lib/plugin-manager/plugin-record-origin.js +46 -0
  299. package/src/lib/plugin-manager/plugin-record-origin.js.map +1 -0
  300. package/src/lib/plugin-manager/plugin-record-pages.d.ts +37 -0
  301. package/src/lib/plugin-manager/plugin-record-pages.js +52 -0
  302. package/src/lib/plugin-manager/plugin-record-pages.js.map +1 -0
  303. package/src/lib/plugin-manager/plugin-record-timeline.d.ts +60 -0
  304. package/src/lib/plugin-manager/plugin-record-timeline.js +16 -0
  305. package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
  306. package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +5 -5
  307. package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -1
  308. package/src/lib/plugin-manager/plugin-revocations.d.ts +64 -0
  309. package/src/lib/plugin-manager/plugin-revocations.js +47 -0
  310. package/src/lib/plugin-manager/plugin-revocations.js.map +1 -0
  311. package/src/lib/plugin-manager/plugin-send-tallies.d.ts +69 -0
  312. package/src/lib/plugin-manager/plugin-send-tallies.js +45 -0
  313. package/src/lib/plugin-manager/plugin-send-tallies.js.map +1 -0
  314. package/src/lib/plugin-manager/plugin-server-steps.d.ts +170 -0
  315. package/src/lib/plugin-manager/plugin-server-steps.js +116 -0
  316. package/src/lib/plugin-manager/plugin-server-steps.js.map +1 -0
  317. package/src/lib/plugin-manager/plugin-site-bundle.d.ts +40 -0
  318. package/src/lib/plugin-manager/plugin-site-bundle.js +4 -0
  319. package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -1
  320. package/src/lib/plugin-manager/plugin-site-export.d.ts +57 -1
  321. package/src/lib/plugin-manager/plugin-site-export.js +23 -10
  322. package/src/lib/plugin-manager/plugin-site-export.js.map +1 -1
  323. package/src/lib/plugin-manager/plugin-sitemap-readers.d.ts +146 -0
  324. package/src/lib/plugin-manager/plugin-sitemap-readers.js +110 -0
  325. package/src/lib/plugin-manager/plugin-sitemap-readers.js.map +1 -0
  326. package/src/lib/plugin-manager/plugin-transfer-resources.d.ts +714 -0
  327. package/src/lib/plugin-manager/plugin-transfer-resources.js +443 -0
  328. package/src/lib/plugin-manager/plugin-transfer-resources.js.map +1 -0
  329. package/src/lib/plugin-manager/plugin-usage-axes.d.ts +54 -5
  330. package/src/lib/plugin-manager/plugin-usage-axes.js +11 -3
  331. package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -1
  332. package/src/lib/plugin-manager/plugin-user-erasure.js +9 -1
  333. package/src/lib/plugin-manager/plugin-user-erasure.js.map +1 -1
  334. package/src/lib/plugin-manager/plugin-visitor-doors.d.ts +104 -0
  335. package/src/lib/plugin-manager/plugin-visitor-doors.js +108 -0
  336. package/src/lib/plugin-manager/plugin-visitor-doors.js.map +1 -0
  337. package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
  338. package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
  339. package/src/lib/plugin-manager/repeat-rows.d.ts +5 -6
  340. package/src/lib/plugin-manager/repeat-rows.js.map +1 -1
  341. package/src/lib/app-utils/actions.d.ts +0 -310
  342. package/src/lib/app-utils/actions.js +0 -506
  343. package/src/lib/app-utils/actions.js.map +0 -1
  344. package/src/lib/app-utils/automation-placeholders.d.ts +0 -72
  345. package/src/lib/app-utils/automation-placeholders.js +0 -207
  346. package/src/lib/app-utils/automation-placeholders.js.map +0 -1
  347. package/src/lib/app-utils/dataset-models.d.ts +0 -339
  348. package/src/lib/app-utils/dataset-models.js +0 -722
  349. package/src/lib/app-utils/dataset-models.js.map +0 -1
  350. package/src/lib/app-utils/datasets.d.ts +0 -171
  351. package/src/lib/app-utils/datasets.js +0 -227
  352. package/src/lib/app-utils/datasets.js.map +0 -1
  353. package/src/lib/app-utils/form-abuse-ceiling.d.ts +0 -146
  354. package/src/lib/app-utils/form-abuse-ceiling.js +0 -158
  355. package/src/lib/app-utils/form-abuse-ceiling.js.map +0 -1
  356. package/src/lib/plugin-manager/order-fulfilment.d.ts +0 -142
  357. package/src/lib/plugin-manager/order-fulfilment.js +0 -104
  358. package/src/lib/plugin-manager/order-fulfilment.js.map +0 -1
@@ -181,9 +181,61 @@ export interface PluginRecordDeliveryRequest {
181
181
  /** What the server said, scrubbed of the address; the owner bounds it. */
182
182
  detail?: string | null;
183
183
  }
184
+ /**
185
+ * An email a plugin is about to send to a person (AGL-3080), offered to the
186
+ * record system BEFORE it goes so the entry it files can follow the
187
+ * message's delivery: the record system answers with the provider tags the
188
+ * message has to carry for the delivery webhook to find the entry, and with
189
+ * how to file it once the provider has accepted it.
190
+ *
191
+ * Only a message addressed to the person `link` names — the person an
192
+ * automation's event is about — earns an entry: an alert routed to the
193
+ * merchant's own inbox would put that inbox on a customer's history.
194
+ */
195
+ export interface PluginRecordEmailPrepareRequest {
196
+ orgId: string;
197
+ /** The site the message goes out as: the entry carries its scope. */
198
+ hostId: string;
199
+ /** The address the message is sent to, raw. */
200
+ to: string;
201
+ /** The person the sender means: by id where it holds one, else by address. */
202
+ link: Pick<PluginRecordLink, 'contactId' | 'email'>;
203
+ /**
204
+ * The organization's billing document, when the caller already read it —
205
+ * the record system's plan gate and scope read it; absent, the owner reads
206
+ * it itself.
207
+ */
208
+ org?: unknown;
209
+ }
210
+ /** The message as it was sent, for the entry the record system files. */
211
+ export interface PluginRecordEmailSent {
212
+ subject: string;
213
+ body: string;
214
+ to: string;
215
+ /** When it was accepted, epoch ms; now when absent. */
216
+ atMs?: number;
217
+ /** The sender's own id for what sent it — an automation's id. */
218
+ sourceRef: string;
219
+ }
220
+ /** What the record system answered a prepared email with. */
221
+ export interface PluginRecordPreparedEmail {
222
+ /** Provider tags the message must carry for its delivery to reach the entry. */
223
+ tags: ReadonlyArray<{
224
+ name: string;
225
+ value: string;
226
+ }>;
227
+ /** Files the entry, once the provider accepted the message. Never throws. */
228
+ file(sent: PluginRecordEmailSent): Promise<void>;
229
+ }
184
230
  export interface PluginRecordTimelineWriter {
185
231
  logActivity(request: PluginRecordActivityRequest): Promise<PluginRecordWrite>;
186
232
  createTask(request: PluginRecordTaskRequest): Promise<PluginRecordWrite>;
233
+ /**
234
+ * Prepares the entry an email to a person will earn (AGL-3080). Optional:
235
+ * a record system that files no sent mail answers nothing. `null` for a
236
+ * message that earns no entry. Never throws.
237
+ */
238
+ prepareEmail?(request: PluginRecordEmailPrepareRequest): Promise<PluginRecordPreparedEmail | null>;
187
239
  /**
188
240
  * Marks a filed email bounced or reported (AGL-3245). Optional: a record
189
241
  * system that keeps no delivery state answers nothing, and the caller's
@@ -208,3 +260,11 @@ export interface ResolvedPluginRecordTimelineWriter {
208
260
  }
209
261
  /** The writer, with its owner, or `null` when no plugin keeps records here. */
210
262
  export declare function pluginRecordTimelineWriter(): ResolvedPluginRecordTimelineWriter | null;
263
+ /**
264
+ * Asks whichever plugin keeps records to prepare the entry an email to a
265
+ * person will earn, or answers `null` when none does, the one that does
266
+ * files no sent mail, or this message earns no entry. Never throws: the
267
+ * entry is bookkeeping beside a send, and a lookup that failed must not
268
+ * become a message that never left.
269
+ */
270
+ export declare function preparePluginRecordEmail(request: PluginRecordEmailPrepareRequest): Promise<PluginRecordPreparedEmail | null>;
@@ -35,5 +35,21 @@ export const PLUGIN_RECORD_TIMELINE = definePluginServiceContract('core.record-t
35
35
  writer: entry.impl
36
36
  } : null;
37
37
  }
38
+ /**
39
+ * Asks whichever plugin keeps records to prepare the entry an email to a
40
+ * person will earn, or answers `null` when none does, the one that does
41
+ * files no sent mail, or this message earns no entry. Never throws: the
42
+ * entry is bookkeeping beside a send, and a lookup that failed must not
43
+ * become a message that never left.
44
+ */ export async function preparePluginRecordEmail(request) {
45
+ const resolved = pluginRecordTimelineWriter();
46
+ if (!(resolved == null ? void 0 : resolved.writer.prepareEmail)) return null;
47
+ try {
48
+ return await resolved.writer.prepareEmail(request);
49
+ } catch (error) {
50
+ console.error('[record-timeline] the record system could not prepare an email entry', error);
51
+ return null;
52
+ }
53
+ }
38
54
 
39
55
  //# sourceMappingURL=plugin-record-timeline.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-record-timeline.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\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * An entry one plugin files on a record another plugin keeps (AGL-2981).\n *\n * A person and the company they work for are records of the workspace's\n * record system, and what happened with them — an email sent, a reply\n * received, a call to make — belongs on their timeline, whichever plugin it\n * happened in.\n * A plugin that sends mail or books a meeting must not write the record\n * system's documents itself: it would restate the owner's rules — where an\n * entry lives, who may see it, how a copy of the same email is told apart,\n * how many entries a record may carry — and drift from them the day the\n * owner changes one. Nor may it import the owner, which the package map\n * forbids.\n *\n * So the record system registers a WRITER here, from its server surfaces,\n * and a caller asks for it. Every rule stays the owner's:\n *\n * - the entry is stamped with the scope a record made on the site would\n * carry, so it is visible to exactly who sees the record;\n * - an EMAIL is filed once per `Message-ID`, under the id the owner files a\n * copy of the same message by through any other door — a copy the rep\n * forwarded to a capture address is the same entry, not a second one;\n * - any other entry, and every task, is filed once per the caller's own\n * `dedupeKey`, so a caller that runs again finds what it wrote rather\n * than writing it twice;\n * - a record whose log is full, or a workspace whose plan carries no record\n * system, is refused — answered, never thrown;\n * - a caller that knows a record only as the owner handed it over — a kind\n * and an id carried on a link — or knows only the person's address is\n * answered with the record the owner finds for it, on that site, or\n * refused with a 404 when it finds none.\n *\n * A single-implementation contract: a workspace keeps one record system.\n *\n * ## The caller proves who is asking\n *\n * Like `plugin-resource-drafts`, the registry authenticates nobody. The\n * caller decides, in its own terms and before it asks, that the entry is\n * the workspace's to write — that the record is one it acted on, for the\n * member it acted for.\n */\n\n/**\n * The record an entry is filed on: the person (a contact, or a lead not yet\n * one) and the company they work for, as the owner links them — or, from a\n * caller that holds no id of the owner's, how to find the record.\n *\n * The ids win where given, and are filed on as named. Otherwise `record`,\n * then `email`: the owner looks the record up as the entry's site sees it,\n * links whatever it groups that record under itself, and refuses the entry\n * with a 404 when it finds nothing.\n */\nexport interface PluginRecordLink {\n contactId?: string\n companyId?: string\n /**\n * A lead not yet converted (AGL-3234) — the record system's own id for\n * it, addressed under `hostId`. A sequence's emails and tasks land on the\n * lead's page while the person is one, and follow the lead to the contact\n * it becomes.\n */\n leadId?: string\n /**\n * A record the owner handed the caller, by its kind and id in the owner's\n * own words, and carried back unread (AGL-2660): the record a booking link\n * was dropped from, through the zone the owner drew it in. A kind the\n * owner does not keep, or a record the site cannot see, is passed over for\n * `email` rather than refused.\n */\n record?: { kind: string; id: string } | null\n /**\n * The person at this address, as the entry's site knows them: what the\n * entry lands on when nothing above names a record the owner finds — a\n * booking taken off the widget cold.\n */\n email?: string | null\n}\n\n/** Where an entry is filed, and by which plugin. */\nexport interface PluginRecordEntryContext {\n orgId: string\n /** The site whose scope the entry carries: as if a member made it there. */\n hostId: string\n link: PluginRecordLink\n /** The plugin filing it, recorded on the entry. */\n sourcePluginId: string\n}\n\n/** What an activity is, in the record system's own words. */\nexport type PluginRecordActivityKind = 'email' | 'call' | 'meeting' | 'note' | 'other'\n\n/** The message an `email` activity is about. */\nexport interface PluginRecordEmail {\n /** `outbound` for one the workspace wrote; `inbound` for one written to it. */\n direction: 'outbound' | 'inbound'\n subject: string\n /** The address on the message's From. */\n from: string\n /** The address it was written to, when one is worth showing. */\n to: string | null\n /** The `Message-ID` header, angle brackets included: what files it once. */\n messageId: string\n /** The `Message-ID` it answered, when it answered one. */\n inReplyTo?: string | null\n}\n\nexport interface PluginRecordActivityRequest extends PluginRecordEntryContext {\n kind: PluginRecordActivityKind\n /** When it happened, epoch ms. */\n atMs: number\n /** Plain text: an email's excerpt, a note's words. The owner bounds it. */\n body: string\n /** The member it is by, or `''` for none. */\n byUid: string\n byName?: string | null\n /** Required for an `email`, and read only for one. */\n email?: PluginRecordEmail | null\n /** Required for every kind but `email`: the caller's id for this entry. */\n dedupeKey?: string | null\n}\n\n/** What a task is, in the record system's own words. */\nexport type PluginRecordTaskKind = 'call' | 'email' | 'meeting' | 'todo'\n\nexport interface PluginRecordTaskRequest extends PluginRecordEntryContext {\n /** The caller's id for this task: the same key never makes a second task. */\n dedupeKey: string\n title: string\n notes?: string | null\n kind: PluginRecordTaskKind\n /** When it is due, epoch ms. */\n dueAtMs: number\n /**\n * The member it is for, `''` for nobody, or `null` for whoever holds the\n * record it lands on — the caller that found the record by `record` or\n * `email` does not know who that is.\n */\n assigneeUid: string | null\n /** The member who made it happen, or `''` when nobody did. */\n createdByUid: string\n}\n\n/**\n * The owner's answer. `created: false` is the entry a previous write — or a\n * copy through another door — already filed, under the same `id`.\n */\nexport type PluginRecordWrite =\n | { ok: true; id: string; created: boolean }\n | {\n ok: false\n status: 400 | 403 | 404 | 409\n /** Customer-safe: a caller may show or log it as it stands. */\n error: string\n }\n\n/**\n * What became of an email a plugin filed (AGL-3245): the receiving server\n * bounced it, or the recipient reported it. Addressed by the `Message-ID`\n * the send was filed under, so the verdict lands on the send's own entry\n * and the record reads Sent, then Bounced.\n */\nexport interface PluginRecordDeliveryRequest {\n orgId: string\n /** The `Message-ID` header of the send, angle brackets included. */\n messageId: string\n state: 'bounced' | 'complained'\n /** When it happened, epoch ms. */\n atMs: number\n /** What the server said, scrubbed of the address; the owner bounds it. */\n detail?: string | null\n}\n\nexport interface PluginRecordTimelineWriter {\n logActivity(request: PluginRecordActivityRequest): Promise<PluginRecordWrite>\n createTask(request: PluginRecordTaskRequest): Promise<PluginRecordWrite>\n /**\n * Marks a filed email bounced or reported (AGL-3245). Optional: a record\n * system that keeps no delivery state answers nothing, and the caller's\n * entry stands as filed.\n */\n recordEmailDelivery?(request: PluginRecordDeliveryRequest): Promise<PluginRecordWrite>\n}\n\nexport const PLUGIN_RECORD_TIMELINE = definePluginServiceContract<PluginRecordTimelineWriter>(\n 'core.record-timeline',\n { multiple: false },\n)\n\n/**\n * Registers the workspace's record timeline writer. The owner is the loader's\n * marker when a register fn is running, else `options.pluginId`; with neither\n * the registration throws, and a second plugin's writer is refused naming\n * both — the incumbent keeps serving.\n */\nexport function registerPluginRecordTimelineWriter(\n writer: PluginRecordTimelineWriter,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_RECORD_TIMELINE, writer, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\nexport interface ResolvedPluginRecordTimelineWriter {\n /** The plugin that keeps the records. */\n pluginId: string\n writer: PluginRecordTimelineWriter\n}\n\n/** The writer, with its owner, or `null` when no plugin keeps records here. */\nexport function pluginRecordTimelineWriter(): ResolvedPluginRecordTimelineWriter | null {\n const entry = resolvePluginServices(PLUGIN_RECORD_TIMELINE)[0]\n return entry ? { pluginId: entry.pluginId, writer: entry.impl } : null\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_RECORD_TIMELINE","multiple","registerPluginRecordTimelineWriter","writer","options","pluginId","pluginRecordTimelineWriter","entry","impl"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AAyL1B,OAAO,MAAMC,yBAAyBH,4BACpC,wBACA;IAAEI,UAAU;AAAM,GACnB;AAED;;;;;CAKC,GACD,OAAO,SAASC,mCACdC,MAAkC,EAClCC,OAA+B;IAE/BN,sBAAsBE,wBAAwBG,QAAQ,aAChDC,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAQA,6EAA6E,GAC7E,OAAO,SAASC;IACd,MAAMC,QAAQR,sBAAsBC,uBAAuB,CAAC,EAAE;IAC9D,OAAOO,QAAQ;QAAEF,UAAUE,MAAMF,QAAQ;QAAEF,QAAQI,MAAMC,IAAI;IAAC,IAAI;AACpE"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-record-timeline.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\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * An entry one plugin files on a record another plugin keeps (AGL-2981).\n *\n * A person and the company they work for are records of the workspace's\n * record system, and what happened with them — an email sent, a reply\n * received, a call to make — belongs on their timeline, whichever plugin it\n * happened in.\n * A plugin that sends mail or books a meeting must not write the record\n * system's documents itself: it would restate the owner's rules — where an\n * entry lives, who may see it, how a copy of the same email is told apart,\n * how many entries a record may carry — and drift from them the day the\n * owner changes one. Nor may it import the owner, which the package map\n * forbids.\n *\n * So the record system registers a WRITER here, from its server surfaces,\n * and a caller asks for it. Every rule stays the owner's:\n *\n * - the entry is stamped with the scope a record made on the site would\n * carry, so it is visible to exactly who sees the record;\n * - an EMAIL is filed once per `Message-ID`, under the id the owner files a\n * copy of the same message by through any other door — a copy the rep\n * forwarded to a capture address is the same entry, not a second one;\n * - any other entry, and every task, is filed once per the caller's own\n * `dedupeKey`, so a caller that runs again finds what it wrote rather\n * than writing it twice;\n * - a record whose log is full, or a workspace whose plan carries no record\n * system, is refused — answered, never thrown;\n * - a caller that knows a record only as the owner handed it over — a kind\n * and an id carried on a link — or knows only the person's address is\n * answered with the record the owner finds for it, on that site, or\n * refused with a 404 when it finds none.\n *\n * A single-implementation contract: a workspace keeps one record system.\n *\n * ## The caller proves who is asking\n *\n * Like `plugin-resource-drafts`, the registry authenticates nobody. The\n * caller decides, in its own terms and before it asks, that the entry is\n * the workspace's to write — that the record is one it acted on, for the\n * member it acted for.\n */\n\n/**\n * The record an entry is filed on: the person (a contact, or a lead not yet\n * one) and the company they work for, as the owner links them — or, from a\n * caller that holds no id of the owner's, how to find the record.\n *\n * The ids win where given, and are filed on as named. Otherwise `record`,\n * then `email`: the owner looks the record up as the entry's site sees it,\n * links whatever it groups that record under itself, and refuses the entry\n * with a 404 when it finds nothing.\n */\nexport interface PluginRecordLink {\n contactId?: string\n companyId?: string\n /**\n * A lead not yet converted (AGL-3234) — the record system's own id for\n * it, addressed under `hostId`. A sequence's emails and tasks land on the\n * lead's page while the person is one, and follow the lead to the contact\n * it becomes.\n */\n leadId?: string\n /**\n * A record the owner handed the caller, by its kind and id in the owner's\n * own words, and carried back unread (AGL-2660): the record a booking link\n * was dropped from, through the zone the owner drew it in. A kind the\n * owner does not keep, or a record the site cannot see, is passed over for\n * `email` rather than refused.\n */\n record?: { kind: string; id: string } | null\n /**\n * The person at this address, as the entry's site knows them: what the\n * entry lands on when nothing above names a record the owner finds — a\n * booking taken off the widget cold.\n */\n email?: string | null\n}\n\n/** Where an entry is filed, and by which plugin. */\nexport interface PluginRecordEntryContext {\n orgId: string\n /** The site whose scope the entry carries: as if a member made it there. */\n hostId: string\n link: PluginRecordLink\n /** The plugin filing it, recorded on the entry. */\n sourcePluginId: string\n}\n\n/** What an activity is, in the record system's own words. */\nexport type PluginRecordActivityKind = 'email' | 'call' | 'meeting' | 'note' | 'other'\n\n/** The message an `email` activity is about. */\nexport interface PluginRecordEmail {\n /** `outbound` for one the workspace wrote; `inbound` for one written to it. */\n direction: 'outbound' | 'inbound'\n subject: string\n /** The address on the message's From. */\n from: string\n /** The address it was written to, when one is worth showing. */\n to: string | null\n /** The `Message-ID` header, angle brackets included: what files it once. */\n messageId: string\n /** The `Message-ID` it answered, when it answered one. */\n inReplyTo?: string | null\n}\n\nexport interface PluginRecordActivityRequest extends PluginRecordEntryContext {\n kind: PluginRecordActivityKind\n /** When it happened, epoch ms. */\n atMs: number\n /** Plain text: an email's excerpt, a note's words. The owner bounds it. */\n body: string\n /** The member it is by, or `''` for none. */\n byUid: string\n byName?: string | null\n /** Required for an `email`, and read only for one. */\n email?: PluginRecordEmail | null\n /** Required for every kind but `email`: the caller's id for this entry. */\n dedupeKey?: string | null\n}\n\n/** What a task is, in the record system's own words. */\nexport type PluginRecordTaskKind = 'call' | 'email' | 'meeting' | 'todo'\n\nexport interface PluginRecordTaskRequest extends PluginRecordEntryContext {\n /** The caller's id for this task: the same key never makes a second task. */\n dedupeKey: string\n title: string\n notes?: string | null\n kind: PluginRecordTaskKind\n /** When it is due, epoch ms. */\n dueAtMs: number\n /**\n * The member it is for, `''` for nobody, or `null` for whoever holds the\n * record it lands on — the caller that found the record by `record` or\n * `email` does not know who that is.\n */\n assigneeUid: string | null\n /** The member who made it happen, or `''` when nobody did. */\n createdByUid: string\n}\n\n/**\n * The owner's answer. `created: false` is the entry a previous write — or a\n * copy through another door — already filed, under the same `id`.\n */\nexport type PluginRecordWrite =\n | { ok: true; id: string; created: boolean }\n | {\n ok: false\n status: 400 | 403 | 404 | 409\n /** Customer-safe: a caller may show or log it as it stands. */\n error: string\n }\n\n/**\n * What became of an email a plugin filed (AGL-3245): the receiving server\n * bounced it, or the recipient reported it. Addressed by the `Message-ID`\n * the send was filed under, so the verdict lands on the send's own entry\n * and the record reads Sent, then Bounced.\n */\nexport interface PluginRecordDeliveryRequest {\n orgId: string\n /** The `Message-ID` header of the send, angle brackets included. */\n messageId: string\n state: 'bounced' | 'complained'\n /** When it happened, epoch ms. */\n atMs: number\n /** What the server said, scrubbed of the address; the owner bounds it. */\n detail?: string | null\n}\n\n/**\n * An email a plugin is about to send to a person (AGL-3080), offered to the\n * record system BEFORE it goes so the entry it files can follow the\n * message's delivery: the record system answers with the provider tags the\n * message has to carry for the delivery webhook to find the entry, and with\n * how to file it once the provider has accepted it.\n *\n * Only a message addressed to the person `link` names — the person an\n * automation's event is about — earns an entry: an alert routed to the\n * merchant's own inbox would put that inbox on a customer's history.\n */\nexport interface PluginRecordEmailPrepareRequest {\n orgId: string\n /** The site the message goes out as: the entry carries its scope. */\n hostId: string\n /** The address the message is sent to, raw. */\n to: string\n /** The person the sender means: by id where it holds one, else by address. */\n link: Pick<PluginRecordLink, 'contactId' | 'email'>\n /**\n * The organization's billing document, when the caller already read it —\n * the record system's plan gate and scope read it; absent, the owner reads\n * it itself.\n */\n org?: unknown\n}\n\n/** The message as it was sent, for the entry the record system files. */\nexport interface PluginRecordEmailSent {\n subject: string\n body: string\n to: string\n /** When it was accepted, epoch ms; now when absent. */\n atMs?: number\n /** The sender's own id for what sent it — an automation's id. */\n sourceRef: string\n}\n\n/** What the record system answered a prepared email with. */\nexport interface PluginRecordPreparedEmail {\n /** Provider tags the message must carry for its delivery to reach the entry. */\n tags: ReadonlyArray<{ name: string; value: string }>\n /** Files the entry, once the provider accepted the message. Never throws. */\n file(sent: PluginRecordEmailSent): Promise<void>\n}\n\nexport interface PluginRecordTimelineWriter {\n logActivity(request: PluginRecordActivityRequest): Promise<PluginRecordWrite>\n createTask(request: PluginRecordTaskRequest): Promise<PluginRecordWrite>\n /**\n * Prepares the entry an email to a person will earn (AGL-3080). Optional:\n * a record system that files no sent mail answers nothing. `null` for a\n * message that earns no entry. Never throws.\n */\n prepareEmail?(request: PluginRecordEmailPrepareRequest): Promise<PluginRecordPreparedEmail | null>\n /**\n * Marks a filed email bounced or reported (AGL-3245). Optional: a record\n * system that keeps no delivery state answers nothing, and the caller's\n * entry stands as filed.\n */\n recordEmailDelivery?(request: PluginRecordDeliveryRequest): Promise<PluginRecordWrite>\n}\n\nexport const PLUGIN_RECORD_TIMELINE = definePluginServiceContract<PluginRecordTimelineWriter>(\n 'core.record-timeline',\n { multiple: false },\n)\n\n/**\n * Registers the workspace's record timeline writer. The owner is the loader's\n * marker when a register fn is running, else `options.pluginId`; with neither\n * the registration throws, and a second plugin's writer is refused naming\n * both — the incumbent keeps serving.\n */\nexport function registerPluginRecordTimelineWriter(\n writer: PluginRecordTimelineWriter,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_RECORD_TIMELINE, writer, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\nexport interface ResolvedPluginRecordTimelineWriter {\n /** The plugin that keeps the records. */\n pluginId: string\n writer: PluginRecordTimelineWriter\n}\n\n/** The writer, with its owner, or `null` when no plugin keeps records here. */\nexport function pluginRecordTimelineWriter(): ResolvedPluginRecordTimelineWriter | null {\n const entry = resolvePluginServices(PLUGIN_RECORD_TIMELINE)[0]\n return entry ? { pluginId: entry.pluginId, writer: entry.impl } : null\n}\n\n/**\n * Asks whichever plugin keeps records to prepare the entry an email to a\n * person will earn, or answers `null` when none does, the one that does\n * files no sent mail, or this message earns no entry. Never throws: the\n * entry is bookkeeping beside a send, and a lookup that failed must not\n * become a message that never left.\n */\nexport async function preparePluginRecordEmail(\n request: PluginRecordEmailPrepareRequest,\n): Promise<PluginRecordPreparedEmail | null> {\n const resolved = pluginRecordTimelineWriter()\n if (!resolved?.writer.prepareEmail) return null\n try {\n return await resolved.writer.prepareEmail(request)\n } catch (error) {\n console.error('[record-timeline] the record system could not prepare an email entry', error)\n return null\n }\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_RECORD_TIMELINE","multiple","registerPluginRecordTimelineWriter","writer","options","pluginId","pluginRecordTimelineWriter","entry","impl","preparePluginRecordEmail","request","resolved","prepareEmail","error","console"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AA6O1B,OAAO,MAAMC,yBAAyBH,4BACpC,wBACA;IAAEI,UAAU;AAAM,GACnB;AAED;;;;;CAKC,GACD,OAAO,SAASC,mCACdC,MAAkC,EAClCC,OAA+B;IAE/BN,sBAAsBE,wBAAwBG,QAAQ,aAChDC,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAQA,6EAA6E,GAC7E,OAAO,SAASC;IACd,MAAMC,QAAQR,sBAAsBC,uBAAuB,CAAC,EAAE;IAC9D,OAAOO,QAAQ;QAAEF,UAAUE,MAAMF,QAAQ;QAAEF,QAAQI,MAAMC,IAAI;IAAC,IAAI;AACpE;AAEA;;;;;;CAMC,GACD,OAAO,eAAeC,yBACpBC,OAAwC;IAExC,MAAMC,WAAWL;IACjB,IAAI,EAACK,4BAAAA,SAAUR,MAAM,CAACS,YAAY,GAAE,OAAO;IAC3C,IAAI;QACF,OAAO,MAAMD,SAASR,MAAM,CAACS,YAAY,CAACF;IAC5C,EAAE,OAAOG,OAAO;QACdC,QAAQD,KAAK,CAAC,wEAAwEA;QACtF,OAAO;IACT;AACF"}
@@ -45,11 +45,11 @@ import type { ReusableComponentTree } from '../app-utils/compose-reusable-compon
45
45
  *
46
46
  * ## The registry carries no authorization of the CALLER
47
47
  *
48
- * Like `order-fulfilment`, a writer is a pre-authorized operation. It applies
49
- * the owner's rules to the member the draft is for, and knows nothing about
50
- * whether the caller may act for that member. A caller establishes, in its
51
- * own terms and before it asks: who is asking, that the org owns the site,
52
- * and that the owning plugin is switched on for that site.
48
+ * A writer is a pre-authorized operation. It applies the owner's rules to the
49
+ * member the draft is for, and knows nothing about whether the caller may act
50
+ * for that member. A caller establishes, in its own terms and before it asks:
51
+ * who is asking, that the org owns the site, and that the owning plugin is
52
+ * switched on for that site.
53
53
  *
54
54
  * ## One writer per resource
55
55
  *
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-resource-drafts.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\nimport type { ReusableComponentTree } from '../app-utils/compose-reusable-components'\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * Drafts one plugin writes for another (AGL-2912).\n *\n * A resource belongs to the plugin that models it: the document's shape, the\n * allowance a create counts against, who may create one, and what makes one\n * well-formed. A different plugin that produces such a resource — an importer\n * turning a file into pages, a generator turning a brief into an email, a\n * migration bringing campaigns over from another tool — must not write the\n * document itself, because it would restate the owner's rules and drift from\n * them the day the owner changes one. Nor may it import the owner, which the\n * package map forbids.\n *\n * So the owner registers a WRITER for the resource from its server surfaces,\n * and a caller asks for one by resource name. Every rule stays the owner's:\n *\n * - `refusal` answers, before the caller spends anything, whether this\n * member may create one on this site now: their role, the site's room;\n * - `check` answers, synchronously and without I/O, whether content is\n * well-formed, so a caller can hold what it produces to the owner's rules\n * before it keeps it;\n * - `read` reports the draft already written under an id, so a caller that\n * runs again finds its draft rather than making a second;\n * - `write` makes the draft, meets the allowance inside its own write, and\n * never publishes, schedules or sends anything.\n *\n * Built on the typed service registry (`plugin-services`): one contract, every\n * writer registered under its resource name as the service's key.\n *\n * ## The registry carries no authorization of the CALLER\n *\n * Like `order-fulfilment`, a writer is a pre-authorized operation. It applies\n * the owner's rules to the member the draft is for, and knows nothing about\n * whether the caller may act for that member. A caller establishes, in its\n * own terms and before it asks: who is asking, that the org owns the site,\n * and that the owning plugin is switched on for that site.\n *\n * ## One writer per resource\n *\n * A resource has one owner. A second plugin registering a writer for a\n * resource another plugin already writes is refused, naming both, and the\n * incumbent keeps serving; the same plugin registering again — from its second\n * server surface, or on a hot reload — replaces its own.\n */\n\n/** Who a draft is for, on which site, and when. */\nexport interface PluginDraftContext {\n orgId: string\n hostId: string\n /** The member the draft is made for: the owner applies its rules to them and records them as the author. */\n uid: string\n /** The org document the caller already read, for the owner's entitlement and allowance reads. */\n org: Readonly<Record<string, unknown>> | null\n now: Date\n}\n\n/** Why a draft cannot be made. */\nexport interface PluginDraftRefusal {\n status: 400 | 403 | 404 | 409\n /** Customer-safe: a caller shows it as it stands. */\n error: string\n}\n\n/** A draft that exists. */\nexport interface PluginDraftRecord {\n id: string\n name: string\n /** The version the draft opens on, where the resource has versions. */\n versionId: string | null\n /** What the owner reports about the draft beyond its identity, in the shape its writer documents. */\n facts: Readonly<Record<string, unknown>>\n}\n\nexport interface PluginDraftRequest extends PluginDraftContext {\n /** The draft's id, chosen by the caller: one per act, so a write asked again finds its draft. */\n id: string\n /** The name asked for; the owner may number it to keep it unique. */\n name: string\n /** The resource's content, in the shape the owner's writer documents and validates. */\n content: Readonly<Record<string, unknown>>\n}\n\nexport type PluginDraftCheck =\n | { ok: true; facts: Readonly<Record<string, unknown>> }\n | { ok: false; problems: string[] }\n\n/** What a check is told beside the content. */\nexport interface PluginDraftCheckContext {\n hostId: string\n /**\n * The site's published reusable components the content places, keyed by id\n * — what `loadReferencedComponents` reads (AGL-3287).\n *\n * `check` does no I/O, so a caller whose content may place a component loads\n * the definitions first and hands them in; a writer whose resource renders\n * placed components composes them before judging, so what passes is what\n * would render. Absent means none were loaded, and the content is judged as\n * written.\n */\n components?: Readonly<Record<string, ReusableComponentTree | undefined>>\n}\n\nexport type PluginDraftWrite =\n | (PluginDraftRecord & { ok: true; replayed: boolean })\n | (PluginDraftRefusal & { ok: false })\n\nexport interface PluginResourceDraftWriter {\n /** Whether this member may create one on this site now; `null` admits. */\n refusal(context: PluginDraftContext): Promise<PluginDraftRefusal | null>\n /** Whether content is well-formed, with what the owner derived from it. Pure. */\n check(\n content: Readonly<Record<string, unknown>>,\n context: PluginDraftCheckContext,\n ): PluginDraftCheck\n /** The draft written under `id`, or `null`. */\n read(context: { hostId: string; id: string }): Promise<PluginDraftRecord | null>\n /** Makes the draft; a refusal is returned, never thrown. */\n write(request: PluginDraftRequest): Promise<PluginDraftWrite>\n}\n\nexport const PLUGIN_RESOURCE_DRAFTS =\n definePluginServiceContract<PluginResourceDraftWriter>('core.resource-drafts', {\n multiple: true,\n })\n\n/**\n * Registers the writer for a resource. The owner is the loader's marker when\n * a register fn is running, else `options.pluginId`; with neither the\n * registration throws. A writer for a resource another plugin writes throws\n * naming both.\n */\nexport function registerPluginResourceDraftWriter(\n resource: string,\n writer: PluginResourceDraftWriter,\n options?: { pluginId?: string },\n): void {\n const key = resource.trim()\n if (!key) throw new Error('a resource draft writer needs a resource name')\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n const incumbent = resolvePluginServices(PLUGIN_RESOURCE_DRAFTS).find(\n (entry) => entry.key === key,\n )\n if (incumbent && pluginId && incumbent.pluginId !== pluginId) {\n throw new Error(\n `resource \"${key}\" already has a draft writer from \"${incumbent.pluginId}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n registerPluginService(PLUGIN_RESOURCE_DRAFTS, writer, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n key,\n })\n}\n\nexport interface ResolvedPluginDraftWriter {\n /** The plugin that owns the resource. */\n pluginId: string\n writer: PluginResourceDraftWriter\n}\n\n/** The writer for a resource, with its owner, or `null` when no plugin writes it. */\nexport function pluginResourceDraftWriter(resource: string): ResolvedPluginDraftWriter | null {\n const key = resource.trim()\n const entry = resolvePluginServices(PLUGIN_RESOURCE_DRAFTS).find((one) => one.key === key)\n return entry ? { pluginId: entry.pluginId, writer: entry.impl } : null\n}\n"],"names":["getRegisteringPluginId","definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_RESOURCE_DRAFTS","multiple","registerPluginResourceDraftWriter","resource","writer","options","key","trim","Error","pluginId","incumbent","find","entry","pluginResourceDraftWriter","one","impl"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SAASA,sBAAsB,QAAQ,qCAAiC;AACxE,SACEC,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AAyH1B,OAAO,MAAMC,yBACXH,4BAAuD,wBAAwB;IAC7EI,UAAU;AACZ,GAAE;AAEJ;;;;;CAKC,GACD,OAAO,SAASC,kCACdC,QAAgB,EAChBC,MAAiC,EACjCC,OAA+B;QAIbT,MAAAA;IAFlB,MAAMU,MAAMH,SAASI,IAAI;IACzB,IAAI,CAACD,KAAK,MAAM,IAAIE,MAAM;IAC1B,MAAMC,WAAW,EAACb,QAAAA,0BAAAA,oCAAAA,0BAA4BS,2BAAAA,QAASI,QAAQ,YAA7Cb,OAAiD,IAAIW,IAAI;IAC3E,MAAMG,YAAYX,sBAAsBC,wBAAwBW,IAAI,CAClE,CAACC,QAAUA,MAAMN,GAAG,KAAKA;IAE3B,IAAII,aAAaD,YAAYC,UAAUD,QAAQ,KAAKA,UAAU;QAC5D,MAAM,IAAID,MACR,CAAC,UAAU,EAAEF,IAAI,mCAAmC,EAAEI,UAAUD,QAAQ,CAAC,GAAG,CAAC,GAC3E,CAAC,SAAS,EAAEA,SAAS,CAAC,CAAC;IAE7B;IACAX,sBAAsBE,wBAAwBI,QAAQ,aAChDC,CAAAA,2BAAAA,QAASI,QAAQ,IAAG;QAAEA,UAAUJ,QAAQI,QAAQ;IAAC,IAAI,CAAC;QAC1DH;;AAEJ;AAQA,mFAAmF,GACnF,OAAO,SAASO,0BAA0BV,QAAgB;IACxD,MAAMG,MAAMH,SAASI,IAAI;IACzB,MAAMK,QAAQb,sBAAsBC,wBAAwBW,IAAI,CAAC,CAACG,MAAQA,IAAIR,GAAG,KAAKA;IACtF,OAAOM,QAAQ;QAAEH,UAAUG,MAAMH,QAAQ;QAAEL,QAAQQ,MAAMG,IAAI;IAAC,IAAI;AACpE"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-resource-drafts.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\nimport type { ReusableComponentTree } from '../app-utils/compose-reusable-components'\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * Drafts one plugin writes for another (AGL-2912).\n *\n * A resource belongs to the plugin that models it: the document's shape, the\n * allowance a create counts against, who may create one, and what makes one\n * well-formed. A different plugin that produces such a resource — an importer\n * turning a file into pages, a generator turning a brief into an email, a\n * migration bringing campaigns over from another tool — must not write the\n * document itself, because it would restate the owner's rules and drift from\n * them the day the owner changes one. Nor may it import the owner, which the\n * package map forbids.\n *\n * So the owner registers a WRITER for the resource from its server surfaces,\n * and a caller asks for one by resource name. Every rule stays the owner's:\n *\n * - `refusal` answers, before the caller spends anything, whether this\n * member may create one on this site now: their role, the site's room;\n * - `check` answers, synchronously and without I/O, whether content is\n * well-formed, so a caller can hold what it produces to the owner's rules\n * before it keeps it;\n * - `read` reports the draft already written under an id, so a caller that\n * runs again finds its draft rather than making a second;\n * - `write` makes the draft, meets the allowance inside its own write, and\n * never publishes, schedules or sends anything.\n *\n * Built on the typed service registry (`plugin-services`): one contract, every\n * writer registered under its resource name as the service's key.\n *\n * ## The registry carries no authorization of the CALLER\n *\n * A writer is a pre-authorized operation. It applies the owner's rules to the\n * member the draft is for, and knows nothing about whether the caller may act\n * for that member. A caller establishes, in its own terms and before it asks:\n * who is asking, that the org owns the site, and that the owning plugin is\n * switched on for that site.\n *\n * ## One writer per resource\n *\n * A resource has one owner. A second plugin registering a writer for a\n * resource another plugin already writes is refused, naming both, and the\n * incumbent keeps serving; the same plugin registering again — from its second\n * server surface, or on a hot reload — replaces its own.\n */\n\n/** Who a draft is for, on which site, and when. */\nexport interface PluginDraftContext {\n orgId: string\n hostId: string\n /** The member the draft is made for: the owner applies its rules to them and records them as the author. */\n uid: string\n /** The org document the caller already read, for the owner's entitlement and allowance reads. */\n org: Readonly<Record<string, unknown>> | null\n now: Date\n}\n\n/** Why a draft cannot be made. */\nexport interface PluginDraftRefusal {\n status: 400 | 403 | 404 | 409\n /** Customer-safe: a caller shows it as it stands. */\n error: string\n}\n\n/** A draft that exists. */\nexport interface PluginDraftRecord {\n id: string\n name: string\n /** The version the draft opens on, where the resource has versions. */\n versionId: string | null\n /** What the owner reports about the draft beyond its identity, in the shape its writer documents. */\n facts: Readonly<Record<string, unknown>>\n}\n\nexport interface PluginDraftRequest extends PluginDraftContext {\n /** The draft's id, chosen by the caller: one per act, so a write asked again finds its draft. */\n id: string\n /** The name asked for; the owner may number it to keep it unique. */\n name: string\n /** The resource's content, in the shape the owner's writer documents and validates. */\n content: Readonly<Record<string, unknown>>\n}\n\nexport type PluginDraftCheck =\n | { ok: true; facts: Readonly<Record<string, unknown>> }\n | { ok: false; problems: string[] }\n\n/** What a check is told beside the content. */\nexport interface PluginDraftCheckContext {\n hostId: string\n /**\n * The site's published reusable components the content places, keyed by id\n * — what `loadReferencedComponents` reads (AGL-3287).\n *\n * `check` does no I/O, so a caller whose content may place a component loads\n * the definitions first and hands them in; a writer whose resource renders\n * placed components composes them before judging, so what passes is what\n * would render. Absent means none were loaded, and the content is judged as\n * written.\n */\n components?: Readonly<Record<string, ReusableComponentTree | undefined>>\n}\n\nexport type PluginDraftWrite =\n | (PluginDraftRecord & { ok: true; replayed: boolean })\n | (PluginDraftRefusal & { ok: false })\n\nexport interface PluginResourceDraftWriter {\n /** Whether this member may create one on this site now; `null` admits. */\n refusal(context: PluginDraftContext): Promise<PluginDraftRefusal | null>\n /** Whether content is well-formed, with what the owner derived from it. Pure. */\n check(\n content: Readonly<Record<string, unknown>>,\n context: PluginDraftCheckContext,\n ): PluginDraftCheck\n /** The draft written under `id`, or `null`. */\n read(context: { hostId: string; id: string }): Promise<PluginDraftRecord | null>\n /** Makes the draft; a refusal is returned, never thrown. */\n write(request: PluginDraftRequest): Promise<PluginDraftWrite>\n}\n\nexport const PLUGIN_RESOURCE_DRAFTS =\n definePluginServiceContract<PluginResourceDraftWriter>('core.resource-drafts', {\n multiple: true,\n })\n\n/**\n * Registers the writer for a resource. The owner is the loader's marker when\n * a register fn is running, else `options.pluginId`; with neither the\n * registration throws. A writer for a resource another plugin writes throws\n * naming both.\n */\nexport function registerPluginResourceDraftWriter(\n resource: string,\n writer: PluginResourceDraftWriter,\n options?: { pluginId?: string },\n): void {\n const key = resource.trim()\n if (!key) throw new Error('a resource draft writer needs a resource name')\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n const incumbent = resolvePluginServices(PLUGIN_RESOURCE_DRAFTS).find(\n (entry) => entry.key === key,\n )\n if (incumbent && pluginId && incumbent.pluginId !== pluginId) {\n throw new Error(\n `resource \"${key}\" already has a draft writer from \"${incumbent.pluginId}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n registerPluginService(PLUGIN_RESOURCE_DRAFTS, writer, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n key,\n })\n}\n\nexport interface ResolvedPluginDraftWriter {\n /** The plugin that owns the resource. */\n pluginId: string\n writer: PluginResourceDraftWriter\n}\n\n/** The writer for a resource, with its owner, or `null` when no plugin writes it. */\nexport function pluginResourceDraftWriter(resource: string): ResolvedPluginDraftWriter | null {\n const key = resource.trim()\n const entry = resolvePluginServices(PLUGIN_RESOURCE_DRAFTS).find((one) => one.key === key)\n return entry ? { pluginId: entry.pluginId, writer: entry.impl } : null\n}\n"],"names":["getRegisteringPluginId","definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_RESOURCE_DRAFTS","multiple","registerPluginResourceDraftWriter","resource","writer","options","key","trim","Error","pluginId","incumbent","find","entry","pluginResourceDraftWriter","one","impl"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SAASA,sBAAsB,QAAQ,qCAAiC;AACxE,SACEC,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AAyH1B,OAAO,MAAMC,yBACXH,4BAAuD,wBAAwB;IAC7EI,UAAU;AACZ,GAAE;AAEJ;;;;;CAKC,GACD,OAAO,SAASC,kCACdC,QAAgB,EAChBC,MAAiC,EACjCC,OAA+B;QAIbT,MAAAA;IAFlB,MAAMU,MAAMH,SAASI,IAAI;IACzB,IAAI,CAACD,KAAK,MAAM,IAAIE,MAAM;IAC1B,MAAMC,WAAW,EAACb,QAAAA,0BAAAA,oCAAAA,0BAA4BS,2BAAAA,QAASI,QAAQ,YAA7Cb,OAAiD,IAAIW,IAAI;IAC3E,MAAMG,YAAYX,sBAAsBC,wBAAwBW,IAAI,CAClE,CAACC,QAAUA,MAAMN,GAAG,KAAKA;IAE3B,IAAII,aAAaD,YAAYC,UAAUD,QAAQ,KAAKA,UAAU;QAC5D,MAAM,IAAID,MACR,CAAC,UAAU,EAAEF,IAAI,mCAAmC,EAAEI,UAAUD,QAAQ,CAAC,GAAG,CAAC,GAC3E,CAAC,SAAS,EAAEA,SAAS,CAAC,CAAC;IAE7B;IACAX,sBAAsBE,wBAAwBI,QAAQ,aAChDC,CAAAA,2BAAAA,QAASI,QAAQ,IAAG;QAAEA,UAAUJ,QAAQI,QAAQ;IAAC,IAAI,CAAC;QAC1DH;;AAEJ;AAQA,mFAAmF,GACnF,OAAO,SAASO,0BAA0BV,QAAgB;IACxD,MAAMG,MAAMH,SAASI,IAAI;IACzB,MAAMK,QAAQb,sBAAsBC,wBAAwBW,IAAI,CAAC,CAACG,MAAQA,IAAIR,GAAG,KAAKA;IACtF,OAAOM,QAAQ;QAAEH,UAAUG,MAAMH,QAAQ;QAAEL,QAAQQ,MAAMG,IAAI;IAAC,IAAI;AACpE"}
@@ -0,0 +1,64 @@
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
+ import type { PluginRevocation } from '../app-utils/plugin-manifest';
18
+ /**
19
+ * The platform's kill switch, read by a plugin that is not the one that keeps
20
+ * it (AGL-3080).
21
+ *
22
+ * An artifact installed from a distribution channel — an email design, a
23
+ * component, a plugin — carries the listing it came from on its install
24
+ * stamp (`app-utils/artifact-provenance.ts`). When the platform pulls that
25
+ * listing, or one of its versions, the revocation (`PluginRevocation`, the
26
+ * platform's own shape) is what every reader consults: the loader before it
27
+ * runs a bundle, the send path before it mails a design that was installed
28
+ * rather than written. The revocations are KEPT by the plugin that runs the
29
+ * distribution channel, and a reader that is not that plugin asks through
30
+ * this slot rather than reading its storage.
31
+ *
32
+ * ## Absent, and failed, are different answers
33
+ *
34
+ * No reader registered means nothing in this process distributes artifacts,
35
+ * so nothing here could have been installed from a listing and there is
36
+ * nothing to revoke: {@link readListingRevocation} answers `null` — after
37
+ * running the app's boot step once, because a boot whose declarations
38
+ * failed looks the same from here, and a kill switch that silently stopped
39
+ * answering is the one failure it may not have. A reader
40
+ * that FAILS throws through to the caller, which decides — a send that cannot
41
+ * learn whether its design was pulled refuses rather than mails it, the
42
+ * direction the read had before it was a seam.
43
+ *
44
+ * Server-side: reached by its own subpath, never through
45
+ * `plugin-manager/index.ts`.
46
+ */
47
+ export interface PluginRevocationReader {
48
+ /** The listing's revocation, or `null` when it was never revoked. */
49
+ revocation(listingId: string): Promise<PluginRevocation | null>;
50
+ }
51
+ export declare const PLUGIN_REVOCATIONS: import("./plugin-services").PluginServiceContract<PluginRevocationReader>;
52
+ /**
53
+ * Registers the plugin that keeps the revocations. The owner is the loader's
54
+ * marker when a register fn is running, else `options.pluginId`; a second
55
+ * plugin's reader is refused naming both.
56
+ */
57
+ export declare function registerPluginRevocationReader(reader: PluginRevocationReader, options?: {
58
+ pluginId?: string;
59
+ }): void;
60
+ /**
61
+ * A listing's revocation: `null` when it has none, or when nothing in this
62
+ * process keeps revocations. Throws what a failing reader throws.
63
+ */
64
+ export declare function readListingRevocation(listingId: string): Promise<PluginRevocation | null>;
@@ -0,0 +1,47 @@
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
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ import { runPluginDeclarationsRepair } from "./plugin-declarations-repair.js";
18
+ import { definePluginServiceContract, registerPluginService, resolvePluginService } from "./plugin-services.js";
19
+ export const PLUGIN_REVOCATIONS = definePluginServiceContract('core.revocations', {
20
+ multiple: false
21
+ });
22
+ /**
23
+ * Registers the plugin that keeps the revocations. The owner is the loader's
24
+ * marker when a register fn is running, else `options.pluginId`; a second
25
+ * plugin's reader is refused naming both.
26
+ */ export function registerPluginRevocationReader(reader, options) {
27
+ registerPluginService(PLUGIN_REVOCATIONS, reader, _extends({}, (options == null ? void 0 : options.pluginId) ? {
28
+ pluginId: options.pluginId
29
+ } : {}));
30
+ }
31
+ /**
32
+ * A listing's revocation: `null` when it has none, or when nothing in this
33
+ * process keeps revocations. Throws what a failing reader throws.
34
+ */ export async function readListingRevocation(listingId) {
35
+ const id = String(listingId != null ? listingId : '').trim();
36
+ if (!id) return null;
37
+ let reader = resolvePluginService(PLUGIN_REVOCATIONS);
38
+ if (!reader) {
39
+ await runPluginDeclarationsRepair().catch((error)=>{
40
+ console.error('[revocations] plugin declarations failed', error);
41
+ });
42
+ reader = resolvePluginService(PLUGIN_REVOCATIONS);
43
+ }
44
+ return reader ? reader.revocation(id) : null;
45
+ }
46
+
47
+ //# sourceMappingURL=plugin-revocations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-revocations.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\nimport type { PluginRevocation } from '../app-utils/plugin-manifest'\nimport { runPluginDeclarationsRepair } from './plugin-declarations-repair'\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginService,\n} from './plugin-services'\n\n/**\n * The platform's kill switch, read by a plugin that is not the one that keeps\n * it (AGL-3080).\n *\n * An artifact installed from a distribution channel — an email design, a\n * component, a plugin — carries the listing it came from on its install\n * stamp (`app-utils/artifact-provenance.ts`). When the platform pulls that\n * listing, or one of its versions, the revocation (`PluginRevocation`, the\n * platform's own shape) is what every reader consults: the loader before it\n * runs a bundle, the send path before it mails a design that was installed\n * rather than written. The revocations are KEPT by the plugin that runs the\n * distribution channel, and a reader that is not that plugin asks through\n * this slot rather than reading its storage.\n *\n * ## Absent, and failed, are different answers\n *\n * No reader registered means nothing in this process distributes artifacts,\n * so nothing here could have been installed from a listing and there is\n * nothing to revoke: {@link readListingRevocation} answers `null` — after\n * running the app's boot step once, because a boot whose declarations\n * failed looks the same from here, and a kill switch that silently stopped\n * answering is the one failure it may not have. A reader\n * that FAILS throws through to the caller, which decides — a send that cannot\n * learn whether its design was pulled refuses rather than mails it, the\n * direction the read had before it was a seam.\n *\n * Server-side: reached by its own subpath, never through\n * `plugin-manager/index.ts`.\n */\n\nexport interface PluginRevocationReader {\n /** The listing's revocation, or `null` when it was never revoked. */\n revocation(listingId: string): Promise<PluginRevocation | null>\n}\n\nexport const PLUGIN_REVOCATIONS = definePluginServiceContract<PluginRevocationReader>(\n 'core.revocations',\n { multiple: false },\n)\n\n/**\n * Registers the plugin that keeps the revocations. The owner is the loader's\n * marker when a register fn is running, else `options.pluginId`; a second\n * plugin's reader is refused naming both.\n */\nexport function registerPluginRevocationReader(\n reader: PluginRevocationReader,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_REVOCATIONS, reader, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/**\n * A listing's revocation: `null` when it has none, or when nothing in this\n * process keeps revocations. Throws what a failing reader throws.\n */\nexport async function readListingRevocation(listingId: string): Promise<PluginRevocation | null> {\n const id = String(listingId ?? '').trim()\n if (!id) return null\n let reader = resolvePluginService(PLUGIN_REVOCATIONS)\n if (!reader) {\n await runPluginDeclarationsRepair().catch((error: unknown) => {\n console.error('[revocations] plugin declarations failed', error)\n })\n reader = resolvePluginService(PLUGIN_REVOCATIONS)\n }\n return reader ? reader.revocation(id) : null\n}\n"],"names":["runPluginDeclarationsRepair","definePluginServiceContract","registerPluginService","resolvePluginService","PLUGIN_REVOCATIONS","multiple","registerPluginRevocationReader","reader","options","pluginId","readListingRevocation","listingId","id","String","trim","catch","error","console","revocation"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SAASA,2BAA2B,QAAQ,kCAA8B;AAC1E,SACEC,2BAA2B,EAC3BC,qBAAqB,EACrBC,oBAAoB,QACf,uBAAmB;AAqC1B,OAAO,MAAMC,qBAAqBH,4BAChC,oBACA;IAAEI,UAAU;AAAM,GACnB;AAED;;;;CAIC,GACD,OAAO,SAASC,+BACdC,MAA8B,EAC9BC,OAA+B;IAE/BN,sBAAsBE,oBAAoBG,QAAQ,aAC5CC,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAEA;;;CAGC,GACD,OAAO,eAAeC,sBAAsBC,SAAiB;IAC3D,MAAMC,KAAKC,OAAOF,oBAAAA,YAAa,IAAIG,IAAI;IACvC,IAAI,CAACF,IAAI,OAAO;IAChB,IAAIL,SAASJ,qBAAqBC;IAClC,IAAI,CAACG,QAAQ;QACX,MAAMP,8BAA8Be,KAAK,CAAC,CAACC;YACzCC,QAAQD,KAAK,CAAC,4CAA4CA;QAC5D;QACAT,SAASJ,qBAAqBC;IAChC;IACA,OAAOG,SAASA,OAAOW,UAAU,CAACN,MAAM;AAC1C"}
@@ -0,0 +1,69 @@
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
+ * A bulk send's own figures, moved by a door that is not its sender
19
+ * (AGL-3080).
20
+ *
21
+ * A message a bulk send carried names the send — its id is signed into the
22
+ * unsubscribe link and tagged on the message — and the plugin that serves
23
+ * the site's unsubscribe page learns that a recipient left. That plugin is
24
+ * not the sender: the send, and the figures its report reads, are the
25
+ * plugin's that sent it. So the door reports what happened and the sender
26
+ * counts it, without either importing the other.
27
+ *
28
+ * A MULTIPLE contract: several plugins may send in bulk, and the door does
29
+ * not know which one a send id is. Each tally answers whether the send was
30
+ * its own and counted; the first that answers yes ends the ask.
31
+ *
32
+ * ## The caller proves what happened
33
+ *
34
+ * The registry authenticates nobody. A door counts only what it has already
35
+ * written: an unsubscribe is counted once, when its suppression was created,
36
+ * never on a second click of the same link.
37
+ *
38
+ * Server-side: reached by its own subpath, never through
39
+ * `plugin-manager/index.ts`.
40
+ */
41
+ /** A send, as a link or a message tag names it. */
42
+ export interface PluginSendTallyRequest {
43
+ /** The site whose mail it was. */
44
+ hostId: string;
45
+ /** The send's id, as signed into the link. */
46
+ sendId: string;
47
+ }
48
+ export interface PluginSendTally {
49
+ /**
50
+ * One more recipient left from this send's mail. Answers whether the send
51
+ * is this plugin's and was counted; a send it does not keep is `false`.
52
+ */
53
+ unsubscribed(request: PluginSendTallyRequest): Promise<boolean>;
54
+ }
55
+ export declare const PLUGIN_SEND_TALLIES: import("./plugin-services").PluginServiceContract<PluginSendTally>;
56
+ /**
57
+ * Registers a sender's tally. The owner is the loader's marker when a
58
+ * register fn is running, else `options.pluginId`; registering again under
59
+ * the same plugin replaces in place.
60
+ */
61
+ export declare function registerPluginSendTally(tally: PluginSendTally, options?: {
62
+ pluginId?: string;
63
+ }): void;
64
+ /**
65
+ * Tells the sender of a send that a recipient left. Never throws: the door's
66
+ * own write — the suppression — has landed, and a figure must never be able
67
+ * to cost it. Answers whether any sender counted it.
68
+ */
69
+ export declare function tallySendUnsubscribe(request: PluginSendTallyRequest): Promise<boolean>;
@@ -0,0 +1,45 @@
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
+ */ import { definePluginServiceContract, registerPluginService, resolvePluginServices } from "./plugin-services.js";
18
+ export const PLUGIN_SEND_TALLIES = definePluginServiceContract('core.send-tallies', {
19
+ multiple: true
20
+ });
21
+ /**
22
+ * Registers a sender's tally. The owner is the loader's marker when a
23
+ * register fn is running, else `options.pluginId`; registering again under
24
+ * the same plugin replaces in place.
25
+ */ export function registerPluginSendTally(tally, options) {
26
+ registerPluginService(PLUGIN_SEND_TALLIES, tally, _extends({}, (options == null ? void 0 : options.pluginId) ? {
27
+ pluginId: options.pluginId
28
+ } : {}));
29
+ }
30
+ /**
31
+ * Tells the sender of a send that a recipient left. Never throws: the door's
32
+ * own write — the suppression — has landed, and a figure must never be able
33
+ * to cost it. Answers whether any sender counted it.
34
+ */ export async function tallySendUnsubscribe(request) {
35
+ for (const entry of resolvePluginServices(PLUGIN_SEND_TALLIES)){
36
+ try {
37
+ if (await entry.impl.unsubscribed(request)) return true;
38
+ } catch (error) {
39
+ console.error(`[send-tallies] ${entry.pluginId} failed on ${request.hostId}`, error);
40
+ }
41
+ }
42
+ return false;
43
+ }
44
+
45
+ //# sourceMappingURL=plugin-send-tallies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-send-tallies.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\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * A bulk send's own figures, moved by a door that is not its sender\n * (AGL-3080).\n *\n * A message a bulk send carried names the send — its id is signed into the\n * unsubscribe link and tagged on the message — and the plugin that serves\n * the site's unsubscribe page learns that a recipient left. That plugin is\n * not the sender: the send, and the figures its report reads, are the\n * plugin's that sent it. So the door reports what happened and the sender\n * counts it, without either importing the other.\n *\n * A MULTIPLE contract: several plugins may send in bulk, and the door does\n * not know which one a send id is. Each tally answers whether the send was\n * its own and counted; the first that answers yes ends the ask.\n *\n * ## The caller proves what happened\n *\n * The registry authenticates nobody. A door counts only what it has already\n * written: an unsubscribe is counted once, when its suppression was created,\n * never on a second click of the same link.\n *\n * Server-side: reached by its own subpath, never through\n * `plugin-manager/index.ts`.\n */\n\n/** A send, as a link or a message tag names it. */\nexport interface PluginSendTallyRequest {\n /** The site whose mail it was. */\n hostId: string\n /** The send's id, as signed into the link. */\n sendId: string\n}\n\nexport interface PluginSendTally {\n /**\n * One more recipient left from this send's mail. Answers whether the send\n * is this plugin's and was counted; a send it does not keep is `false`.\n */\n unsubscribed(request: PluginSendTallyRequest): Promise<boolean>\n}\n\nexport const PLUGIN_SEND_TALLIES = definePluginServiceContract<PluginSendTally>(\n 'core.send-tallies',\n { multiple: true },\n)\n\n/**\n * Registers a sender's tally. The owner is the loader's marker when a\n * register fn is running, else `options.pluginId`; registering again under\n * the same plugin replaces in place.\n */\nexport function registerPluginSendTally(\n tally: PluginSendTally,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_SEND_TALLIES, tally, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/**\n * Tells the sender of a send that a recipient left. Never throws: the door's\n * own write — the suppression — has landed, and a figure must never be able\n * to cost it. Answers whether any sender counted it.\n */\nexport async function tallySendUnsubscribe(request: PluginSendTallyRequest): Promise<boolean> {\n for (const entry of resolvePluginServices(PLUGIN_SEND_TALLIES)) {\n try {\n if (await entry.impl.unsubscribed(request)) return true\n } catch (error) {\n console.error(`[send-tallies] ${entry.pluginId} failed on ${request.hostId}`, error)\n }\n }\n return false\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_SEND_TALLIES","multiple","registerPluginSendTally","tally","options","pluginId","tallySendUnsubscribe","request","entry","impl","unsubscribed","error","console","hostId"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AA2C1B,OAAO,MAAMC,sBAAsBH,4BACjC,qBACA;IAAEI,UAAU;AAAK,GAClB;AAED;;;;CAIC,GACD,OAAO,SAASC,wBACdC,KAAsB,EACtBC,OAA+B;IAE/BN,sBAAsBE,qBAAqBG,OAAO,aAC5CC,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAEA;;;;CAIC,GACD,OAAO,eAAeC,qBAAqBC,OAA+B;IACxE,KAAK,MAAMC,SAAST,sBAAsBC,qBAAsB;QAC9D,IAAI;YACF,IAAI,MAAMQ,MAAMC,IAAI,CAACC,YAAY,CAACH,UAAU,OAAO;QACrD,EAAE,OAAOI,OAAO;YACdC,QAAQD,KAAK,CAAC,CAAC,eAAe,EAAEH,MAAMH,QAAQ,CAAC,WAAW,EAAEE,QAAQM,MAAM,EAAE,EAAEF;QAChF;IACF;IACA,OAAO;AACT"}