@baruk/core 0.3.1 → 0.4.2

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 (696) hide show
  1. package/.baruk-provenance.json +10 -0
  2. package/CHANGELOG.md +85 -0
  3. package/dist/auth/password-reset.d.ts +30 -1
  4. package/dist/auth/password-reset.d.ts.map +1 -1
  5. package/dist/auth/password-reset.js +139 -11
  6. package/dist/auth/password-reset.js.map +1 -1
  7. package/dist/auth/service.d.ts +39 -2
  8. package/dist/auth/service.d.ts.map +1 -1
  9. package/dist/auth/service.js +75 -10
  10. package/dist/auth/service.js.map +1 -1
  11. package/dist/billing/ar-repository.d.ts +334 -0
  12. package/dist/billing/ar-repository.d.ts.map +1 -0
  13. package/dist/billing/ar-repository.js +707 -0
  14. package/dist/billing/ar-repository.js.map +1 -0
  15. package/dist/billing/auto-generation.d.ts +87 -0
  16. package/dist/billing/auto-generation.d.ts.map +1 -0
  17. package/dist/billing/auto-generation.js +181 -0
  18. package/dist/billing/auto-generation.js.map +1 -0
  19. package/dist/billing/live-guard.d.ts +64 -0
  20. package/dist/billing/live-guard.d.ts.map +1 -0
  21. package/dist/billing/live-guard.js +68 -0
  22. package/dist/billing/live-guard.js.map +1 -0
  23. package/dist/billing/payment-means-catalog.d.ts +17 -0
  24. package/dist/billing/payment-means-catalog.d.ts.map +1 -0
  25. package/dist/billing/payment-means-catalog.js +21 -0
  26. package/dist/billing/payment-means-catalog.js.map +1 -0
  27. package/dist/billing/payment-means.d.ts +38 -0
  28. package/dist/billing/payment-means.d.ts.map +1 -0
  29. package/dist/billing/payment-means.js +29 -0
  30. package/dist/billing/payment-means.js.map +1 -0
  31. package/dist/billing/payment-rail.d.ts +118 -0
  32. package/dist/billing/payment-rail.d.ts.map +1 -0
  33. package/dist/billing/payment-rail.js +295 -0
  34. package/dist/billing/payment-rail.js.map +1 -0
  35. package/dist/billing/provider/asaas.d.ts +46 -1
  36. package/dist/billing/provider/asaas.d.ts.map +1 -1
  37. package/dist/billing/provider/asaas.js +194 -14
  38. package/dist/billing/provider/asaas.js.map +1 -1
  39. package/dist/billing/provider/manual.js +1 -1
  40. package/dist/billing/provider/manual.js.map +1 -1
  41. package/dist/billing/provider/types.d.ts +115 -8
  42. package/dist/billing/provider/types.d.ts.map +1 -1
  43. package/dist/billing/provider-account.d.ts +89 -0
  44. package/dist/billing/provider-account.d.ts.map +1 -0
  45. package/dist/billing/provider-account.js +161 -0
  46. package/dist/billing/provider-account.js.map +1 -0
  47. package/dist/billing/provider-onboarding.d.ts +67 -0
  48. package/dist/billing/provider-onboarding.d.ts.map +1 -0
  49. package/dist/billing/provider-onboarding.js +234 -0
  50. package/dist/billing/provider-onboarding.js.map +1 -0
  51. package/dist/billing/receivable.d.ts +5 -1
  52. package/dist/billing/receivable.d.ts.map +1 -1
  53. package/dist/billing/reconcile.d.ts +58 -0
  54. package/dist/billing/reconcile.d.ts.map +1 -0
  55. package/dist/billing/reconcile.js +138 -0
  56. package/dist/billing/reconcile.js.map +1 -0
  57. package/dist/billing/repository.d.ts +90 -1
  58. package/dist/billing/repository.d.ts.map +1 -1
  59. package/dist/billing/repository.js +148 -19
  60. package/dist/billing/repository.js.map +1 -1
  61. package/dist/cjs/auth/password-reset.js +141 -11
  62. package/dist/cjs/auth/password-reset.js.map +1 -1
  63. package/dist/cjs/auth/service.js +75 -9
  64. package/dist/cjs/auth/service.js.map +1 -1
  65. package/dist/cjs/billing/ar-repository.js +728 -0
  66. package/dist/cjs/billing/ar-repository.js.map +1 -0
  67. package/dist/cjs/billing/auto-generation.js +186 -0
  68. package/dist/cjs/billing/auto-generation.js.map +1 -0
  69. package/dist/cjs/billing/live-guard.js +72 -0
  70. package/dist/cjs/billing/live-guard.js.map +1 -0
  71. package/dist/cjs/billing/payment-means-catalog.js +25 -0
  72. package/dist/cjs/billing/payment-means-catalog.js.map +1 -0
  73. package/dist/cjs/billing/payment-means.js +33 -0
  74. package/dist/cjs/billing/payment-means.js.map +1 -0
  75. package/dist/cjs/billing/payment-rail.js +301 -0
  76. package/dist/cjs/billing/payment-rail.js.map +1 -0
  77. package/dist/cjs/billing/provider/asaas.js +194 -14
  78. package/dist/cjs/billing/provider/asaas.js.map +1 -1
  79. package/dist/cjs/billing/provider/manual.js +1 -1
  80. package/dist/cjs/billing/provider/manual.js.map +1 -1
  81. package/dist/cjs/billing/provider-account.js +170 -0
  82. package/dist/cjs/billing/provider-account.js.map +1 -0
  83. package/dist/cjs/billing/provider-onboarding.js +239 -0
  84. package/dist/cjs/billing/provider-onboarding.js.map +1 -0
  85. package/dist/cjs/billing/reconcile.js +143 -0
  86. package/dist/cjs/billing/reconcile.js.map +1 -0
  87. package/dist/cjs/billing/repository.js +150 -18
  88. package/dist/cjs/billing/repository.js.map +1 -1
  89. package/dist/cjs/clients/repository.js +96 -20
  90. package/dist/cjs/clients/repository.js.map +1 -1
  91. package/dist/cjs/collection/branding.js +140 -0
  92. package/dist/cjs/collection/branding.js.map +1 -0
  93. package/dist/cjs/collection/channel-accounts.js +137 -0
  94. package/dist/cjs/collection/channel-accounts.js.map +1 -0
  95. package/dist/cjs/collection/channel.js +17 -0
  96. package/dist/cjs/collection/channel.js.map +1 -0
  97. package/dist/cjs/collection/communication-bridge.js +140 -0
  98. package/dist/cjs/collection/communication-bridge.js.map +1 -0
  99. package/dist/cjs/collection/communication-runtime.js +193 -0
  100. package/dist/cjs/collection/communication-runtime.js.map +1 -0
  101. package/dist/cjs/collection/consent-repository.js +84 -0
  102. package/dist/cjs/collection/consent-repository.js.map +1 -0
  103. package/dist/cjs/collection/copy.js +125 -0
  104. package/dist/cjs/collection/copy.js.map +1 -0
  105. package/dist/cjs/collection/delivery-callback.js +151 -0
  106. package/dist/cjs/collection/delivery-callback.js.map +1 -0
  107. package/dist/cjs/collection/email-layout.js +252 -0
  108. package/dist/cjs/collection/email-layout.js.map +1 -0
  109. package/dist/cjs/collection/engine.js +414 -0
  110. package/dist/cjs/collection/engine.js.map +1 -0
  111. package/dist/cjs/collection/format.js +76 -0
  112. package/dist/cjs/collection/format.js.map +1 -0
  113. package/dist/cjs/collection/payment-block.js +3 -0
  114. package/dist/cjs/collection/payment-block.js.map +1 -0
  115. package/dist/cjs/collection/policy.js +147 -0
  116. package/dist/cjs/collection/policy.js.map +1 -0
  117. package/dist/cjs/collection/repository.js +260 -0
  118. package/dist/cjs/collection/repository.js.map +1 -0
  119. package/dist/cjs/collection/subject.js +104 -0
  120. package/dist/cjs/collection/subject.js.map +1 -0
  121. package/dist/cjs/collection/template-catalog.js +165 -0
  122. package/dist/cjs/collection/template-catalog.js.map +1 -0
  123. package/dist/cjs/collection/template.js +78 -0
  124. package/dist/cjs/collection/template.js.map +1 -0
  125. package/dist/cjs/communication/adapters/email.js +132 -0
  126. package/dist/cjs/communication/adapters/email.js.map +1 -0
  127. package/dist/cjs/communication/adapters/sms.js +127 -0
  128. package/dist/cjs/communication/adapters/sms.js.map +1 -0
  129. package/dist/cjs/communication/adapters/whatsapp-language.js +39 -0
  130. package/dist/cjs/communication/adapters/whatsapp-language.js.map +1 -0
  131. package/dist/cjs/communication/adapters/whatsapp-templates.js +100 -0
  132. package/dist/cjs/communication/adapters/whatsapp-templates.js.map +1 -0
  133. package/dist/cjs/communication/adapters/whatsapp.js +213 -0
  134. package/dist/cjs/communication/adapters/whatsapp.js.map +1 -0
  135. package/dist/cjs/communication/audit.js +61 -0
  136. package/dist/cjs/communication/audit.js.map +1 -0
  137. package/dist/cjs/communication/capabilities.js +76 -0
  138. package/dist/cjs/communication/capabilities.js.map +1 -0
  139. package/dist/cjs/communication/channel.js +53 -0
  140. package/dist/cjs/communication/channel.js.map +1 -0
  141. package/dist/cjs/communication/claim.js +228 -0
  142. package/dist/cjs/communication/claim.js.map +1 -0
  143. package/dist/cjs/communication/consent.js +43 -0
  144. package/dist/cjs/communication/consent.js.map +1 -0
  145. package/dist/cjs/communication/context.js +45 -0
  146. package/dist/cjs/communication/context.js.map +1 -0
  147. package/dist/cjs/communication/credentials.js +121 -0
  148. package/dist/cjs/communication/credentials.js.map +1 -0
  149. package/dist/cjs/communication/dry-run-scenario.js +161 -0
  150. package/dist/cjs/communication/dry-run-scenario.js.map +1 -0
  151. package/dist/cjs/communication/dry-run.js +97 -0
  152. package/dist/cjs/communication/dry-run.js.map +1 -0
  153. package/dist/cjs/communication/engine.js +483 -0
  154. package/dist/cjs/communication/engine.js.map +1 -0
  155. package/dist/cjs/communication/graph.js +50 -0
  156. package/dist/cjs/communication/graph.js.map +1 -0
  157. package/dist/cjs/communication/idempotency.js +26 -0
  158. package/dist/cjs/communication/idempotency.js.map +1 -0
  159. package/dist/cjs/communication/identity.js +110 -0
  160. package/dist/cjs/communication/identity.js.map +1 -0
  161. package/dist/cjs/communication/index.js +135 -0
  162. package/dist/cjs/communication/index.js.map +1 -0
  163. package/dist/cjs/communication/onboarding.js +297 -0
  164. package/dist/cjs/communication/onboarding.js.map +1 -0
  165. package/dist/cjs/communication/policy.js +16 -0
  166. package/dist/cjs/communication/policy.js.map +1 -0
  167. package/dist/cjs/communication/routing.js +77 -0
  168. package/dist/cjs/communication/routing.js.map +1 -0
  169. package/dist/cjs/communication/sender-profile.js +128 -0
  170. package/dist/cjs/communication/sender-profile.js.map +1 -0
  171. package/dist/cjs/communication/status.js +86 -0
  172. package/dist/cjs/communication/status.js.map +1 -0
  173. package/dist/cjs/communication/stores/onboarding.js +135 -0
  174. package/dist/cjs/communication/stores/onboarding.js.map +1 -0
  175. package/dist/cjs/communication/stores/postgres.js +458 -0
  176. package/dist/cjs/communication/stores/postgres.js.map +1 -0
  177. package/dist/cjs/communication/stores/routing.js +334 -0
  178. package/dist/cjs/communication/stores/routing.js.map +1 -0
  179. package/dist/cjs/communication/stores/secrets.js +126 -0
  180. package/dist/cjs/communication/stores/secrets.js.map +1 -0
  181. package/dist/cjs/communication/template-provider.js +22 -0
  182. package/dist/cjs/communication/template-provider.js.map +1 -0
  183. package/dist/cjs/communication/template.js +63 -0
  184. package/dist/cjs/communication/template.js.map +1 -0
  185. package/dist/cjs/communication/webhook-subscription.js +258 -0
  186. package/dist/cjs/communication/webhook-subscription.js.map +1 -0
  187. package/dist/cjs/communication/webhook.js +292 -0
  188. package/dist/cjs/communication/webhook.js.map +1 -0
  189. package/dist/cjs/competence/repository.js +309 -0
  190. package/dist/cjs/competence/repository.js.map +1 -0
  191. package/dist/cjs/contacts/phone.js +192 -0
  192. package/dist/cjs/contacts/phone.js.map +1 -0
  193. package/dist/cjs/db/seed-catalog.js +48 -0
  194. package/dist/cjs/db/seed-catalog.js.map +1 -0
  195. package/dist/cjs/db/seed.js +15 -7
  196. package/dist/cjs/db/seed.js.map +1 -1
  197. package/dist/cjs/documents/repository.js +244 -0
  198. package/dist/cjs/documents/repository.js.map +1 -0
  199. package/dist/cjs/documents/requests.js +136 -0
  200. package/dist/cjs/documents/requests.js.map +1 -0
  201. package/dist/cjs/index.js +406 -39
  202. package/dist/cjs/index.js.map +1 -1
  203. package/dist/cjs/legal/documents.js +125 -3
  204. package/dist/cjs/legal/documents.js.map +1 -1
  205. package/dist/cjs/legal/types.js +1 -0
  206. package/dist/cjs/legal/types.js.map +1 -1
  207. package/dist/cjs/mail/auth-templates.js +29 -0
  208. package/dist/cjs/mail/auth-templates.js.map +1 -0
  209. package/dist/cjs/mail/dedup-store.js +12 -51
  210. package/dist/cjs/mail/dedup-store.js.map +1 -1
  211. package/dist/cjs/mail/index.js +16 -4
  212. package/dist/cjs/mail/index.js.map +1 -1
  213. package/dist/cjs/mail/provider.js +12 -247
  214. package/dist/cjs/mail/provider.js.map +1 -1
  215. package/dist/cjs/mail/resend.js +14 -18
  216. package/dist/cjs/mail/resend.js.map +1 -1
  217. package/dist/cjs/mail/sender-resolver.js +12 -11
  218. package/dist/cjs/mail/sender-resolver.js.map +1 -1
  219. package/dist/cjs/mail/template-renderer.js +11 -16
  220. package/dist/cjs/mail/template-renderer.js.map +1 -1
  221. package/dist/cjs/mail/transactional-outbound.js +117 -0
  222. package/dist/cjs/mail/transactional-outbound.js.map +1 -0
  223. package/dist/cjs/mail/types.js +8 -35
  224. package/dist/cjs/mail/types.js.map +1 -1
  225. package/dist/cjs/portal/provisioning.js +144 -0
  226. package/dist/cjs/portal/provisioning.js.map +1 -0
  227. package/dist/cjs/pricing-engine/canonical.js +42 -0
  228. package/dist/cjs/pricing-engine/canonical.js.map +1 -0
  229. package/dist/cjs/pricing-engine/errors.js +6 -1
  230. package/dist/cjs/pricing-engine/errors.js.map +1 -1
  231. package/dist/cjs/pricing-engine/index.js +12 -1
  232. package/dist/cjs/pricing-engine/index.js.map +1 -1
  233. package/dist/cjs/pricing-engine/pipeline.js +200 -26
  234. package/dist/cjs/pricing-engine/pipeline.js.map +1 -1
  235. package/dist/cjs/pricing-engine/shadow-adapter.js +79 -0
  236. package/dist/cjs/pricing-engine/shadow-adapter.js.map +1 -0
  237. package/dist/cjs/pricing-engine/shadow-diff.js +55 -0
  238. package/dist/cjs/pricing-engine/shadow-diff.js.map +1 -0
  239. package/dist/cjs/pricing-engine/shadow-facade.js +85 -0
  240. package/dist/cjs/pricing-engine/shadow-facade.js.map +1 -0
  241. package/dist/cjs/pricing-engine/shadow-legacy-types.js +19 -0
  242. package/dist/cjs/pricing-engine/shadow-legacy-types.js.map +1 -0
  243. package/dist/cjs/pricing-engine/shadow-metrics.js +34 -0
  244. package/dist/cjs/pricing-engine/shadow-metrics.js.map +1 -0
  245. package/dist/cjs/pricing-engine/shadow-normalizer.js +42 -0
  246. package/dist/cjs/pricing-engine/shadow-normalizer.js.map +1 -0
  247. package/dist/cjs/rbac/authorize.js +28 -0
  248. package/dist/cjs/rbac/authorize.js.map +1 -1
  249. package/dist/cjs/rbac/catalog.js +67 -1
  250. package/dist/cjs/rbac/catalog.js.map +1 -1
  251. package/dist/cjs/rbac/workload-provisioning.js +160 -0
  252. package/dist/cjs/rbac/workload-provisioning.js.map +1 -0
  253. package/dist/cjs/rbac/workload.js +191 -0
  254. package/dist/cjs/rbac/workload.js.map +1 -0
  255. package/dist/cjs/storage/checksum.js +15 -0
  256. package/dist/cjs/storage/checksum.js.map +1 -0
  257. package/dist/cjs/storage/key.js +72 -0
  258. package/dist/cjs/storage/key.js.map +1 -0
  259. package/dist/cjs/storage/local.js +100 -0
  260. package/dist/cjs/storage/local.js.map +1 -0
  261. package/dist/cjs/storage/r2.js +181 -0
  262. package/dist/cjs/storage/r2.js.map +1 -0
  263. package/dist/cjs/storage/registry.js +41 -0
  264. package/dist/cjs/storage/registry.js.map +1 -0
  265. package/dist/cjs/storage/types.js +50 -0
  266. package/dist/cjs/storage/types.js.map +1 -0
  267. package/dist/cjs/subscription-billing/provider/asaas.js +32 -7
  268. package/dist/cjs/subscription-billing/provider/asaas.js.map +1 -1
  269. package/dist/cjs/subscription-billing/provider/disabled.js +8 -0
  270. package/dist/cjs/subscription-billing/provider/disabled.js.map +1 -1
  271. package/dist/cjs/subscription-billing/provider/registry.js +17 -0
  272. package/dist/cjs/subscription-billing/provider/registry.js.map +1 -1
  273. package/dist/cjs/subscription-billing/service.js +57 -8
  274. package/dist/cjs/subscription-billing/service.js.map +1 -1
  275. package/dist/cjs/subscription-billing/types.js.map +1 -1
  276. package/dist/cjs/tenancy/provisioning.js +32 -8
  277. package/dist/cjs/tenancy/provisioning.js.map +1 -1
  278. package/dist/cjs/users/repository.js +119 -2
  279. package/dist/cjs/users/repository.js.map +1 -1
  280. package/dist/cjs/vault/repository.js +81 -0
  281. package/dist/cjs/vault/repository.js.map +1 -1
  282. package/dist/clients/repository.d.ts +42 -0
  283. package/dist/clients/repository.d.ts.map +1 -1
  284. package/dist/clients/repository.js +94 -21
  285. package/dist/clients/repository.js.map +1 -1
  286. package/dist/collection/branding.d.ts +72 -0
  287. package/dist/collection/branding.d.ts.map +1 -0
  288. package/dist/collection/branding.js +136 -0
  289. package/dist/collection/branding.js.map +1 -0
  290. package/dist/collection/channel-accounts.d.ts +57 -0
  291. package/dist/collection/channel-accounts.d.ts.map +1 -0
  292. package/dist/collection/channel-accounts.js +133 -0
  293. package/dist/collection/channel-accounts.js.map +1 -0
  294. package/dist/collection/channel.d.ts +24 -0
  295. package/dist/collection/channel.d.ts.map +1 -0
  296. package/dist/collection/channel.js +16 -0
  297. package/dist/collection/channel.js.map +1 -0
  298. package/dist/collection/communication-bridge.d.ts +66 -0
  299. package/dist/collection/communication-bridge.d.ts.map +1 -0
  300. package/dist/collection/communication-bridge.js +134 -0
  301. package/dist/collection/communication-bridge.js.map +1 -0
  302. package/dist/collection/communication-runtime.d.ts +95 -0
  303. package/dist/collection/communication-runtime.d.ts.map +1 -0
  304. package/dist/collection/communication-runtime.js +187 -0
  305. package/dist/collection/communication-runtime.js.map +1 -0
  306. package/dist/collection/consent-repository.d.ts +32 -0
  307. package/dist/collection/consent-repository.d.ts.map +1 -0
  308. package/dist/collection/consent-repository.js +79 -0
  309. package/dist/collection/consent-repository.js.map +1 -0
  310. package/dist/collection/copy.d.ts +50 -0
  311. package/dist/collection/copy.d.ts.map +1 -0
  312. package/dist/collection/copy.js +122 -0
  313. package/dist/collection/copy.js.map +1 -0
  314. package/dist/collection/delivery-callback.d.ts +49 -0
  315. package/dist/collection/delivery-callback.d.ts.map +1 -0
  316. package/dist/collection/delivery-callback.js +147 -0
  317. package/dist/collection/delivery-callback.js.map +1 -0
  318. package/dist/collection/email-layout.d.ts +45 -0
  319. package/dist/collection/email-layout.d.ts.map +1 -0
  320. package/dist/collection/email-layout.js +247 -0
  321. package/dist/collection/email-layout.js.map +1 -0
  322. package/dist/collection/engine.d.ts +177 -0
  323. package/dist/collection/engine.d.ts.map +1 -0
  324. package/dist/collection/engine.js +407 -0
  325. package/dist/collection/engine.js.map +1 -0
  326. package/dist/collection/format.d.ts +32 -0
  327. package/dist/collection/format.d.ts.map +1 -0
  328. package/dist/collection/format.js +70 -0
  329. package/dist/collection/format.js.map +1 -0
  330. package/dist/collection/payment-block.d.ts +24 -0
  331. package/dist/collection/payment-block.d.ts.map +1 -0
  332. package/dist/collection/payment-block.js +2 -0
  333. package/dist/collection/payment-block.js.map +1 -0
  334. package/dist/collection/policy.d.ts +53 -0
  335. package/dist/collection/policy.d.ts.map +1 -0
  336. package/dist/collection/policy.js +141 -0
  337. package/dist/collection/policy.js.map +1 -0
  338. package/dist/collection/repository.d.ts +129 -0
  339. package/dist/collection/repository.d.ts.map +1 -0
  340. package/dist/collection/repository.js +246 -0
  341. package/dist/collection/repository.js.map +1 -0
  342. package/dist/collection/subject.d.ts +66 -0
  343. package/dist/collection/subject.d.ts.map +1 -0
  344. package/dist/collection/subject.js +99 -0
  345. package/dist/collection/subject.js.map +1 -0
  346. package/dist/collection/template-catalog.d.ts +16 -0
  347. package/dist/collection/template-catalog.d.ts.map +1 -0
  348. package/dist/collection/template-catalog.js +162 -0
  349. package/dist/collection/template-catalog.js.map +1 -0
  350. package/dist/collection/template.d.ts +37 -0
  351. package/dist/collection/template.d.ts.map +1 -0
  352. package/dist/collection/template.js +73 -0
  353. package/dist/collection/template.js.map +1 -0
  354. package/dist/communication/adapters/email.d.ts +28 -0
  355. package/dist/communication/adapters/email.d.ts.map +1 -0
  356. package/dist/communication/adapters/email.js +129 -0
  357. package/dist/communication/adapters/email.js.map +1 -0
  358. package/dist/communication/adapters/sms.d.ts +95 -0
  359. package/dist/communication/adapters/sms.d.ts.map +1 -0
  360. package/dist/communication/adapters/sms.js +121 -0
  361. package/dist/communication/adapters/sms.js.map +1 -0
  362. package/dist/communication/adapters/whatsapp-language.d.ts +34 -0
  363. package/dist/communication/adapters/whatsapp-language.d.ts.map +1 -0
  364. package/dist/communication/adapters/whatsapp-language.js +36 -0
  365. package/dist/communication/adapters/whatsapp-language.js.map +1 -0
  366. package/dist/communication/adapters/whatsapp-templates.d.ts +18 -0
  367. package/dist/communication/adapters/whatsapp-templates.d.ts.map +1 -0
  368. package/dist/communication/adapters/whatsapp-templates.js +97 -0
  369. package/dist/communication/adapters/whatsapp-templates.js.map +1 -0
  370. package/dist/communication/adapters/whatsapp.d.ts +29 -0
  371. package/dist/communication/adapters/whatsapp.d.ts.map +1 -0
  372. package/dist/communication/adapters/whatsapp.js +210 -0
  373. package/dist/communication/adapters/whatsapp.js.map +1 -0
  374. package/dist/communication/audit.d.ts +105 -0
  375. package/dist/communication/audit.d.ts.map +1 -0
  376. package/dist/communication/audit.js +56 -0
  377. package/dist/communication/audit.js.map +1 -0
  378. package/dist/communication/capabilities.d.ts +88 -0
  379. package/dist/communication/capabilities.d.ts.map +1 -0
  380. package/dist/communication/capabilities.js +72 -0
  381. package/dist/communication/capabilities.js.map +1 -0
  382. package/dist/communication/channel.d.ts +125 -0
  383. package/dist/communication/channel.d.ts.map +1 -0
  384. package/dist/communication/channel.js +47 -0
  385. package/dist/communication/channel.js.map +1 -0
  386. package/dist/communication/claim.d.ts +368 -0
  387. package/dist/communication/claim.d.ts.map +1 -0
  388. package/dist/communication/claim.js +224 -0
  389. package/dist/communication/claim.js.map +1 -0
  390. package/dist/communication/consent.d.ts +65 -0
  391. package/dist/communication/consent.d.ts.map +1 -0
  392. package/dist/communication/consent.js +40 -0
  393. package/dist/communication/consent.js.map +1 -0
  394. package/dist/communication/context.d.ts +48 -0
  395. package/dist/communication/context.d.ts.map +1 -0
  396. package/dist/communication/context.js +41 -0
  397. package/dist/communication/context.js.map +1 -0
  398. package/dist/communication/credentials.d.ts +74 -0
  399. package/dist/communication/credentials.d.ts.map +1 -0
  400. package/dist/communication/credentials.js +115 -0
  401. package/dist/communication/credentials.js.map +1 -0
  402. package/dist/communication/dry-run-scenario.d.ts +37 -0
  403. package/dist/communication/dry-run-scenario.d.ts.map +1 -0
  404. package/dist/communication/dry-run-scenario.js +158 -0
  405. package/dist/communication/dry-run-scenario.js.map +1 -0
  406. package/dist/communication/dry-run.d.ts +40 -0
  407. package/dist/communication/dry-run.d.ts.map +1 -0
  408. package/dist/communication/dry-run.js +92 -0
  409. package/dist/communication/dry-run.js.map +1 -0
  410. package/dist/communication/engine.d.ts +153 -0
  411. package/dist/communication/engine.d.ts.map +1 -0
  412. package/dist/communication/engine.js +480 -0
  413. package/dist/communication/engine.js.map +1 -0
  414. package/dist/communication/graph.d.ts +38 -0
  415. package/dist/communication/graph.d.ts.map +1 -0
  416. package/dist/communication/graph.js +45 -0
  417. package/dist/communication/graph.js.map +1 -0
  418. package/dist/communication/idempotency.d.ts +33 -0
  419. package/dist/communication/idempotency.d.ts.map +1 -0
  420. package/dist/communication/idempotency.js +23 -0
  421. package/dist/communication/idempotency.js.map +1 -0
  422. package/dist/communication/identity.d.ts +127 -0
  423. package/dist/communication/identity.d.ts.map +1 -0
  424. package/dist/communication/identity.js +105 -0
  425. package/dist/communication/identity.js.map +1 -0
  426. package/dist/communication/index.d.ts +66 -0
  427. package/dist/communication/index.d.ts.map +1 -0
  428. package/dist/communication/index.js +42 -0
  429. package/dist/communication/index.js.map +1 -0
  430. package/dist/communication/onboarding.d.ts +223 -0
  431. package/dist/communication/onboarding.d.ts.map +1 -0
  432. package/dist/communication/onboarding.js +287 -0
  433. package/dist/communication/onboarding.js.map +1 -0
  434. package/dist/communication/policy.d.ts +99 -0
  435. package/dist/communication/policy.d.ts.map +1 -0
  436. package/dist/communication/policy.js +13 -0
  437. package/dist/communication/policy.js.map +1 -0
  438. package/dist/communication/routing.d.ts +99 -0
  439. package/dist/communication/routing.d.ts.map +1 -0
  440. package/dist/communication/routing.js +73 -0
  441. package/dist/communication/routing.js.map +1 -0
  442. package/dist/communication/sender-profile.d.ts +100 -0
  443. package/dist/communication/sender-profile.d.ts.map +1 -0
  444. package/dist/communication/sender-profile.js +123 -0
  445. package/dist/communication/sender-profile.js.map +1 -0
  446. package/dist/communication/status.d.ts +48 -0
  447. package/dist/communication/status.d.ts.map +1 -0
  448. package/dist/communication/status.js +79 -0
  449. package/dist/communication/status.js.map +1 -0
  450. package/dist/communication/stores/onboarding.d.ts +88 -0
  451. package/dist/communication/stores/onboarding.d.ts.map +1 -0
  452. package/dist/communication/stores/onboarding.js +127 -0
  453. package/dist/communication/stores/onboarding.js.map +1 -0
  454. package/dist/communication/stores/postgres.d.ts +81 -0
  455. package/dist/communication/stores/postgres.d.ts.map +1 -0
  456. package/dist/communication/stores/postgres.js +453 -0
  457. package/dist/communication/stores/postgres.js.map +1 -0
  458. package/dist/communication/stores/routing.d.ts +169 -0
  459. package/dist/communication/stores/routing.d.ts.map +1 -0
  460. package/dist/communication/stores/routing.js +324 -0
  461. package/dist/communication/stores/routing.js.map +1 -0
  462. package/dist/communication/stores/secrets.d.ts +89 -0
  463. package/dist/communication/stores/secrets.d.ts.map +1 -0
  464. package/dist/communication/stores/secrets.js +122 -0
  465. package/dist/communication/stores/secrets.js.map +1 -0
  466. package/dist/communication/template-provider.d.ts +85 -0
  467. package/dist/communication/template-provider.d.ts.map +1 -0
  468. package/dist/communication/template-provider.js +21 -0
  469. package/dist/communication/template-provider.js.map +1 -0
  470. package/dist/communication/template.d.ts +87 -0
  471. package/dist/communication/template.d.ts.map +1 -0
  472. package/dist/communication/template.js +59 -0
  473. package/dist/communication/template.js.map +1 -0
  474. package/dist/communication/webhook-subscription.d.ts +156 -0
  475. package/dist/communication/webhook-subscription.d.ts.map +1 -0
  476. package/dist/communication/webhook-subscription.js +252 -0
  477. package/dist/communication/webhook-subscription.js.map +1 -0
  478. package/dist/communication/webhook.d.ts +121 -0
  479. package/dist/communication/webhook.d.ts.map +1 -0
  480. package/dist/communication/webhook.js +283 -0
  481. package/dist/communication/webhook.js.map +1 -0
  482. package/dist/competence/repository.d.ts +147 -0
  483. package/dist/competence/repository.d.ts.map +1 -0
  484. package/dist/competence/repository.js +294 -0
  485. package/dist/competence/repository.js.map +1 -0
  486. package/dist/contacts/phone.d.ts +70 -0
  487. package/dist/contacts/phone.d.ts.map +1 -0
  488. package/dist/contacts/phone.js +186 -0
  489. package/dist/contacts/phone.js.map +1 -0
  490. package/dist/db/migrate.js +17 -11
  491. package/dist/db/migrate.js.map +1 -1
  492. package/dist/db/seed-catalog.d.ts +18 -0
  493. package/dist/db/seed-catalog.d.ts.map +1 -0
  494. package/dist/db/seed-catalog.js +45 -0
  495. package/dist/db/seed-catalog.js.map +1 -0
  496. package/dist/db/seed.js +16 -8
  497. package/dist/db/seed.js.map +1 -1
  498. package/dist/documents/repository.d.ts +97 -0
  499. package/dist/documents/repository.d.ts.map +1 -0
  500. package/dist/documents/repository.js +236 -0
  501. package/dist/documents/repository.js.map +1 -0
  502. package/dist/documents/requests.d.ts +73 -0
  503. package/dist/documents/requests.d.ts.map +1 -0
  504. package/dist/documents/requests.js +127 -0
  505. package/dist/documents/requests.js.map +1 -0
  506. package/dist/index.d.ts +109 -13
  507. package/dist/index.d.ts.map +1 -1
  508. package/dist/index.js +100 -8
  509. package/dist/index.js.map +1 -1
  510. package/dist/legal/documents.d.ts.map +1 -1
  511. package/dist/legal/documents.js +125 -3
  512. package/dist/legal/documents.js.map +1 -1
  513. package/dist/legal/index.d.ts +1 -1
  514. package/dist/legal/index.d.ts.map +1 -1
  515. package/dist/legal/types.d.ts +32 -1
  516. package/dist/legal/types.d.ts.map +1 -1
  517. package/dist/legal/types.js +1 -0
  518. package/dist/legal/types.js.map +1 -1
  519. package/dist/mail/auth-templates.d.ts +15 -0
  520. package/dist/mail/auth-templates.d.ts.map +1 -0
  521. package/dist/mail/auth-templates.js +26 -0
  522. package/dist/mail/auth-templates.js.map +1 -0
  523. package/dist/mail/dedup-store.d.ts +1 -24
  524. package/dist/mail/dedup-store.d.ts.map +1 -1
  525. package/dist/mail/dedup-store.js +9 -48
  526. package/dist/mail/dedup-store.js.map +1 -1
  527. package/dist/mail/index.d.ts +2 -1
  528. package/dist/mail/index.d.ts.map +1 -1
  529. package/dist/mail/index.js +13 -2
  530. package/dist/mail/index.js.map +1 -1
  531. package/dist/mail/provider.d.ts +2 -30
  532. package/dist/mail/provider.d.ts.map +1 -1
  533. package/dist/mail/provider.js +10 -246
  534. package/dist/mail/provider.js.map +1 -1
  535. package/dist/mail/resend.d.ts +2 -12
  536. package/dist/mail/resend.d.ts.map +1 -1
  537. package/dist/mail/resend.js +11 -17
  538. package/dist/mail/resend.js.map +1 -1
  539. package/dist/mail/sender-resolver.d.ts +1 -7
  540. package/dist/mail/sender-resolver.d.ts.map +1 -1
  541. package/dist/mail/sender-resolver.js +11 -10
  542. package/dist/mail/sender-resolver.js.map +1 -1
  543. package/dist/mail/template-renderer.d.ts +1 -9
  544. package/dist/mail/template-renderer.d.ts.map +1 -1
  545. package/dist/mail/template-renderer.js +10 -15
  546. package/dist/mail/template-renderer.js.map +1 -1
  547. package/dist/mail/transactional-outbound.d.ts +115 -0
  548. package/dist/mail/transactional-outbound.d.ts.map +1 -0
  549. package/dist/mail/transactional-outbound.js +113 -0
  550. package/dist/mail/transactional-outbound.js.map +1 -0
  551. package/dist/mail/types.d.ts +2 -142
  552. package/dist/mail/types.d.ts.map +1 -1
  553. package/dist/mail/types.js +1 -33
  554. package/dist/mail/types.js.map +1 -1
  555. package/dist/portal/provisioning.d.ts +58 -0
  556. package/dist/portal/provisioning.d.ts.map +1 -0
  557. package/dist/portal/provisioning.js +139 -0
  558. package/dist/portal/provisioning.js.map +1 -0
  559. package/dist/pricing-engine/canonical.d.ts +14 -0
  560. package/dist/pricing-engine/canonical.d.ts.map +1 -0
  561. package/dist/pricing-engine/canonical.js +39 -0
  562. package/dist/pricing-engine/canonical.js.map +1 -0
  563. package/dist/pricing-engine/errors.d.ts.map +1 -1
  564. package/dist/pricing-engine/errors.js +6 -1
  565. package/dist/pricing-engine/errors.js.map +1 -1
  566. package/dist/pricing-engine/index.d.ts +12 -2
  567. package/dist/pricing-engine/index.d.ts.map +1 -1
  568. package/dist/pricing-engine/index.js +6 -1
  569. package/dist/pricing-engine/index.js.map +1 -1
  570. package/dist/pricing-engine/pipeline.d.ts.map +1 -1
  571. package/dist/pricing-engine/pipeline.js +202 -28
  572. package/dist/pricing-engine/pipeline.js.map +1 -1
  573. package/dist/pricing-engine/shadow-adapter.d.ts +37 -0
  574. package/dist/pricing-engine/shadow-adapter.d.ts.map +1 -0
  575. package/dist/pricing-engine/shadow-adapter.js +75 -0
  576. package/dist/pricing-engine/shadow-adapter.js.map +1 -0
  577. package/dist/pricing-engine/shadow-diff.d.ts +26 -0
  578. package/dist/pricing-engine/shadow-diff.d.ts.map +1 -0
  579. package/dist/pricing-engine/shadow-diff.js +52 -0
  580. package/dist/pricing-engine/shadow-diff.js.map +1 -0
  581. package/dist/pricing-engine/shadow-facade.d.ts +42 -0
  582. package/dist/pricing-engine/shadow-facade.d.ts.map +1 -0
  583. package/dist/pricing-engine/shadow-facade.js +82 -0
  584. package/dist/pricing-engine/shadow-facade.js.map +1 -0
  585. package/dist/pricing-engine/shadow-legacy-types.d.ts +64 -0
  586. package/dist/pricing-engine/shadow-legacy-types.d.ts.map +1 -0
  587. package/dist/pricing-engine/shadow-legacy-types.js +18 -0
  588. package/dist/pricing-engine/shadow-legacy-types.js.map +1 -0
  589. package/dist/pricing-engine/shadow-metrics.d.ts +33 -0
  590. package/dist/pricing-engine/shadow-metrics.d.ts.map +1 -0
  591. package/dist/pricing-engine/shadow-metrics.js +31 -0
  592. package/dist/pricing-engine/shadow-metrics.js.map +1 -0
  593. package/dist/pricing-engine/shadow-normalizer.d.ts +17 -0
  594. package/dist/pricing-engine/shadow-normalizer.d.ts.map +1 -0
  595. package/dist/pricing-engine/shadow-normalizer.js +39 -0
  596. package/dist/pricing-engine/shadow-normalizer.js.map +1 -0
  597. package/dist/pricing-engine/types.d.ts +2 -0
  598. package/dist/pricing-engine/types.d.ts.map +1 -1
  599. package/dist/rbac/authorize.d.ts +12 -0
  600. package/dist/rbac/authorize.d.ts.map +1 -1
  601. package/dist/rbac/authorize.js +27 -0
  602. package/dist/rbac/authorize.js.map +1 -1
  603. package/dist/rbac/catalog.d.ts.map +1 -1
  604. package/dist/rbac/catalog.js +67 -1
  605. package/dist/rbac/catalog.js.map +1 -1
  606. package/dist/rbac/workload-provisioning.d.ts +66 -0
  607. package/dist/rbac/workload-provisioning.d.ts.map +1 -0
  608. package/dist/rbac/workload-provisioning.js +153 -0
  609. package/dist/rbac/workload-provisioning.js.map +1 -0
  610. package/dist/rbac/workload.d.ts +124 -0
  611. package/dist/rbac/workload.d.ts.map +1 -0
  612. package/dist/rbac/workload.js +184 -0
  613. package/dist/rbac/workload.js.map +1 -0
  614. package/dist/storage/checksum.d.ts +9 -0
  615. package/dist/storage/checksum.d.ts.map +1 -0
  616. package/dist/storage/checksum.js +12 -0
  617. package/dist/storage/checksum.js.map +1 -0
  618. package/dist/storage/key.d.ts +37 -0
  619. package/dist/storage/key.d.ts.map +1 -0
  620. package/dist/storage/key.js +67 -0
  621. package/dist/storage/key.js.map +1 -0
  622. package/dist/storage/local.d.ts +40 -0
  623. package/dist/storage/local.d.ts.map +1 -0
  624. package/dist/storage/local.js +96 -0
  625. package/dist/storage/local.js.map +1 -0
  626. package/dist/storage/r2.d.ts +43 -0
  627. package/dist/storage/r2.d.ts.map +1 -0
  628. package/dist/storage/r2.js +177 -0
  629. package/dist/storage/r2.js.map +1 -0
  630. package/dist/storage/registry.d.ts +23 -0
  631. package/dist/storage/registry.d.ts.map +1 -0
  632. package/dist/storage/registry.js +37 -0
  633. package/dist/storage/registry.js.map +1 -0
  634. package/dist/storage/types.d.ts +67 -0
  635. package/dist/storage/types.d.ts.map +1 -0
  636. package/dist/storage/types.js +45 -0
  637. package/dist/storage/types.js.map +1 -0
  638. package/dist/subscription-billing/provider/asaas.d.ts +14 -0
  639. package/dist/subscription-billing/provider/asaas.d.ts.map +1 -1
  640. package/dist/subscription-billing/provider/asaas.js +32 -7
  641. package/dist/subscription-billing/provider/asaas.js.map +1 -1
  642. package/dist/subscription-billing/provider/disabled.d.ts +9 -0
  643. package/dist/subscription-billing/provider/disabled.d.ts.map +1 -1
  644. package/dist/subscription-billing/provider/disabled.js +8 -0
  645. package/dist/subscription-billing/provider/disabled.js.map +1 -1
  646. package/dist/subscription-billing/provider/registry.d.ts +10 -0
  647. package/dist/subscription-billing/provider/registry.d.ts.map +1 -1
  648. package/dist/subscription-billing/provider/registry.js +17 -0
  649. package/dist/subscription-billing/provider/registry.js.map +1 -1
  650. package/dist/subscription-billing/service.d.ts +17 -1
  651. package/dist/subscription-billing/service.d.ts.map +1 -1
  652. package/dist/subscription-billing/service.js +57 -8
  653. package/dist/subscription-billing/service.js.map +1 -1
  654. package/dist/subscription-billing/types.d.ts +13 -0
  655. package/dist/subscription-billing/types.d.ts.map +1 -1
  656. package/dist/subscription-billing/types.js.map +1 -1
  657. package/dist/tenancy/provisioning.d.ts.map +1 -1
  658. package/dist/tenancy/provisioning.js +32 -8
  659. package/dist/tenancy/provisioning.js.map +1 -1
  660. package/dist/users/repository.d.ts +38 -0
  661. package/dist/users/repository.d.ts.map +1 -1
  662. package/dist/users/repository.js +118 -3
  663. package/dist/users/repository.js.map +1 -1
  664. package/dist/vault/repository.d.ts +67 -0
  665. package/dist/vault/repository.d.ts.map +1 -1
  666. package/dist/vault/repository.js +78 -0
  667. package/dist/vault/repository.js.map +1 -1
  668. package/package.json +13 -4
  669. package/src/db/migrations/0023_user_invite_activation.sql +15 -0
  670. package/src/db/migrations/0024_set_user_password_function.sql +32 -0
  671. package/src/db/migrations/0025_revoke_user_session_function.sql +28 -0
  672. package/src/db/migrations/0026_documents_and_competence.sql +353 -0
  673. package/src/db/migrations/0027_receivable_client_isolation.sql +58 -0
  674. package/src/db/migrations/0028_collection_engine.sql +94 -0
  675. package/src/db/migrations/0029_payment_rail.sql +107 -0
  676. package/src/db/migrations/0030_provider_account_uniqueness.sql +22 -0
  677. package/src/db/migrations/0031_provider_account_environment_scope.sql +21 -0
  678. package/src/db/migrations/0032_settlement_reversal.sql +76 -0
  679. package/src/db/migrations/0033_receivable_idempotency.sql +28 -0
  680. package/src/db/migrations/0034_payment_customer_reconcile.sql +30 -0
  681. package/src/db/migrations/0035_payment_account_environments.sql +61 -0
  682. package/src/db/migrations/0036_primary_backfill_under_force_rls.sql +41 -0
  683. package/src/db/migrations/0037_receivable_generation_source.sql +29 -0
  684. package/src/db/migrations/0038_notification_channels.sql +175 -0
  685. package/src/db/migrations/0039_communication_dispatch_claim.sql +193 -0
  686. package/src/db/migrations/0040_communication_unknown_outcome.sql +99 -0
  687. package/src/db/migrations/0041_channel_binding_routing.sql +146 -0
  688. package/src/db/migrations/0042_channel_route_read_isolation.sql +165 -0
  689. package/src/db/migrations/0043_workload_identity.sql +105 -0
  690. package/src/db/migrations/0044_channel_onboarding_session.sql +96 -0
  691. package/dist/cjs/mail/resend-client.js +0 -103
  692. package/dist/cjs/mail/resend-client.js.map +0 -1
  693. package/dist/mail/resend-client.d.ts +0 -16
  694. package/dist/mail/resend-client.d.ts.map +0 -1
  695. package/dist/mail/resend-client.js +0 -100
  696. package/dist/mail/resend-client.js.map +0 -1
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Diagnóstico da ASSINATURA de webhooks — por que o status não chega.
3
+ *
4
+ * ## O que este módulo responde
5
+ *
6
+ * Uma mensagem aceita pela Meta não produz `delivered` sozinha: o status volta
7
+ * por webhook, e o webhook depende de duas coisas que vivem em lugares
8
+ * DIFERENTES e são configuradas por caminhos diferentes:
9
+ *
10
+ * 1. **A WABA assina o app.** `POST {waba}/subscribed_apps` — feito pelo
11
+ * Embedded Signup, no código (`subscribeAppToWaba`).
12
+ * 2. **O app assina o objeto e declara para onde entregar.**
13
+ * `{app}/subscriptions` com `object=whatsapp_business_account`,
14
+ * `callback_url`, `verify_token` e os `fields` (`messages`) — configurado
15
+ * no painel do app, uma vez, e NUNCA automatizado nesta casa.
16
+ *
17
+ * Ter (1) e não ter (2) produz exatamente o sintoma observado em 2026-09-01: a
18
+ * Meta aceita a mensagem, devolve `wamid`, e não chama ninguém. Do lado de cá
19
+ * não há erro nenhum para ver — o silêncio é a única evidência, e silêncio não
20
+ * aponta causa.
21
+ *
22
+ * ## Por que é leitura pura
23
+ *
24
+ * Este módulo não corrige nada. Corrigir a assinatura do app é mutação externa
25
+ * que muda para onde a Meta entrega os eventos de TODAS as WABAs do app — não é
26
+ * coisa que uma rota de diagnóstico deva poder fazer por engano.
27
+ *
28
+ * ## Sobre o token de app
29
+ *
30
+ * `{app_id}|{app_secret}` é a forma que a Graph API aceita para chamadas em
31
+ * nome do app. O segredo entra na composição do token e **não sai deste
32
+ * módulo**: nem no retorno, nem em erro, nem em log. As respostas carregam só
33
+ * `callback_url` (que é público, é o nosso endpoint), os campos assinados e o
34
+ * estado — nunca o `verify_token`, que a Graph tampouco devolve.
35
+ */
36
+ import { graphUrl } from './graph.js';
37
+ /**
38
+ * Classifica sem propagar a mensagem do provider.
39
+ *
40
+ * O mesmo desenho de `onboarding.ts`: o texto da Meta pode conter identificador
41
+ * de app, de negócio ou trecho de token, e uma rota de diagnóstico é
42
+ * exatamente onde esse texto acabaria numa tela.
43
+ */
44
+ function classify(status) {
45
+ if (status === 401 || status === 403)
46
+ return 'unauthorized';
47
+ if (status === 404)
48
+ return 'not_found';
49
+ return 'provider_error';
50
+ }
51
+ async function ler(url, bearer, opts) {
52
+ const doFetch = opts.fetchImpl ?? fetch;
53
+ let res;
54
+ try {
55
+ res = await doFetch(url, { method: 'GET', headers: { authorization: `Bearer ${bearer}` } });
56
+ }
57
+ catch {
58
+ // A exceção de rede é DESCARTADA inteira: em algumas implementações ela
59
+ // carrega a URL, e a URL de app carrega o token composto.
60
+ return { ok: false, reason: 'network' };
61
+ }
62
+ if (!res.ok)
63
+ return { ok: false, reason: classify(res.status) };
64
+ try {
65
+ return { ok: true, value: (await res.json()) };
66
+ }
67
+ catch {
68
+ return { ok: false, reason: 'provider_error' };
69
+ }
70
+ }
71
+ /**
72
+ * Quais apps a WABA assina — `GET {waba}/subscribed_apps`.
73
+ *
74
+ * Usa o token de NEGÓCIO do tenant (o mesmo do despacho): é a WABA do cliente,
75
+ * e quem tem direito a lê-la é quem tem a credencial dela.
76
+ */
77
+ export async function readWabaSubscribedApps(input, opts = {}) {
78
+ const id = input.wabaId?.trim() ?? '';
79
+ if (!id)
80
+ return { ok: false, reason: 'provider_error' };
81
+ const r = await ler(graphUrl(`${encodeURIComponent(id)}/subscribed_apps`, opts.env), input.accessToken, opts);
82
+ if (!r.ok)
83
+ return r;
84
+ const apps = [];
85
+ for (const item of r.value.data ?? []) {
86
+ const d = item.whatsapp_business_api_data;
87
+ if (d?.id)
88
+ apps.push({ id: d.id, ...(d.name ? { name: d.name } : {}) });
89
+ }
90
+ return { ok: true, value: apps };
91
+ }
92
+ /**
93
+ * O que o APP assina, e para onde entrega — `GET {app}/subscriptions`.
94
+ *
95
+ * Exige token de APP. O segredo é consumido aqui e não atravessa a fronteira:
96
+ * o retorno tem `callback_url`, campos e estado, nada mais.
97
+ */
98
+ export async function readAppSubscriptions(input, opts = {}) {
99
+ const appId = input.appId?.trim() ?? '';
100
+ const secret = input.appSecret?.trim() ?? '';
101
+ if (!appId || !secret)
102
+ return { ok: false, reason: 'unauthorized' };
103
+ const r = await ler(graphUrl(`${encodeURIComponent(appId)}/subscriptions`, opts.env),
104
+ // Token de app. Composto na chamada e descartado com ela.
105
+ `${appId}|${secret}`, opts);
106
+ if (!r.ok)
107
+ return r;
108
+ return {
109
+ ok: true,
110
+ value: (r.value.data ?? []).map((s) => ({
111
+ object: s.object ?? 'unknown',
112
+ ...(s.callback_url ? { callbackUrl: s.callback_url } : {}),
113
+ ...(typeof s.active === 'boolean' ? { active: s.active } : {}),
114
+ // A Graph devolve os campos ora como objeto, ora como string, conforme a
115
+ // versão. Normalizar aqui evita que a rota tenha de conhecer as duas.
116
+ fields: (s.fields ?? [])
117
+ .map((f) => (typeof f === 'string' ? f : (f.name ?? '')))
118
+ .filter((n) => n.length > 0),
119
+ })),
120
+ };
121
+ }
122
+ /**
123
+ * Pede à Meta que ENTREGUE um evento de amostra no callback do app.
124
+ *
125
+ * `POST {app}/subscriptions_sample` — o mesmo botão "Testar" do painel de
126
+ * Webhooks, pela API. **Não manda mensagem de WhatsApp para ninguém**: a Meta
127
+ * monta um payload sintético do campo pedido e o entrega no `callback_url` já
128
+ * configurado, assinado como um evento real.
129
+ *
130
+ * ## Por que isto vale mais que olhar a configuração
131
+ *
132
+ * A leitura acima diz que a configuração ESTÁ certa. Não diz que a entrega
133
+ * ACONTECE. São afirmações diferentes, e a segunda é a que interessa quando o
134
+ * sintoma é silêncio: se a amostra chega, o caminho
135
+ * `Meta → nosso endpoint → assinatura` está provado e a causa é upstream — a
136
+ * Meta não está GERANDO status para este app. Se a amostra não chega, o
137
+ * problema é o caminho, e a configuração correta era uma pista falsa.
138
+ *
139
+ * É a única sonda que discrimina as duas sem gastar uma mensagem real.
140
+ *
141
+ * ## Não altera nada
142
+ *
143
+ * Não cria, não muda e não remove assinatura. O único efeito externo é uma
144
+ * requisição HTTP que a Meta faz ao nosso próprio endpoint público.
145
+ */
146
+ export async function sendWebhookTestEvent(input, opts = {}) {
147
+ const appId = input.appId?.trim() ?? '';
148
+ const secret = input.appSecret?.trim() ?? '';
149
+ if (!appId || !secret)
150
+ return { ok: false, reason: 'unauthorized' };
151
+ const corpo = new URLSearchParams({
152
+ object: input.object ?? 'whatsapp_business_account',
153
+ field: input.field ?? 'messages',
154
+ // Sem isto a Meta entrega só a forma do evento, sem valores — e um payload
155
+ // vazio não exercita a validação de assinatura do mesmo jeito.
156
+ include_values: 'true',
157
+ });
158
+ const doFetch = opts.fetchImpl ?? fetch;
159
+ let res;
160
+ try {
161
+ res = await doFetch(graphUrl(`${encodeURIComponent(appId)}/subscriptions_sample`, opts.env), {
162
+ method: 'POST',
163
+ headers: {
164
+ // Token de app no HEADER. Em query string ele apareceria em log de
165
+ // proxy e em stack trace.
166
+ authorization: `Bearer ${appId}|${secret}`,
167
+ 'content-type': 'application/x-www-form-urlencoded',
168
+ },
169
+ body: corpo.toString(),
170
+ });
171
+ }
172
+ catch {
173
+ return { ok: false, reason: 'network' };
174
+ }
175
+ if (!res.ok)
176
+ return { ok: false, reason: classify(res.status) };
177
+ return { ok: true, value: { requested: true } };
178
+ }
179
+ /**
180
+ * Campos pedidos em CAMADAS, e não numa lista só.
181
+ *
182
+ * A Graph API recusa a requisição INTEIRA quando um único campo do `?fields=`
183
+ * não é legível pela credencial usada — e o que é legível por token de app varia
184
+ * por campo, por versão e por estado do app. Uma lista única transforma "um
185
+ * campo restrito" em "nenhum dado", que foi exatamente o que aconteceu na
186
+ * primeira tentativa: `provider_error` e zero informação, sem dizer qual campo.
187
+ *
188
+ * Em camadas, o que der para ler é lido, e o que faltar aparece nomeado em
189
+ * `unreadableFields` — que é uma resposta útil para quem precisa saber se deve
190
+ * ir ao painel.
191
+ */
192
+ const CAMADAS_DO_APP = [
193
+ // Identidade: se esta falhar, a credencial é que está errada.
194
+ ['id', 'name', 'category', 'link', 'icon_url'],
195
+ // Configuração administrativa — o que a análise da Meta confere.
196
+ ['privacy_policy_url', 'terms_of_service_url', 'app_domains', 'contact_email'],
197
+ // Exclusão de dados: dois campos distintos, e a Meta aceita um OU outro.
198
+ ['data_deletion_url', 'deauth_callback_url'],
199
+ ];
200
+ export async function readAppSettings(input, opts = {}) {
201
+ const appId = input.appId?.trim() ?? '';
202
+ const secret = input.appSecret?.trim() ?? '';
203
+ if (!appId || !secret)
204
+ return { ok: false, reason: 'unauthorized' };
205
+ const token = `${appId}|${secret}`;
206
+ const v = {};
207
+ const ilegiveis = [];
208
+ let algumaPassou = false;
209
+ for (const camada of CAMADAS_DO_APP) {
210
+ const r = await ler(`${graphUrl(encodeURIComponent(appId), opts.env)}?fields=${camada.join(',')}`, token, opts);
211
+ if (r.ok) {
212
+ algumaPassou = true;
213
+ Object.assign(v, r.value);
214
+ }
215
+ else {
216
+ // Não sabemos QUAL campo da camada foi recusado — a Graph não diz. O que
217
+ // se pode afirmar é que nenhum deles veio, e nomeá-los é mais útil do que
218
+ // omitir a camada em silêncio.
219
+ ilegiveis.push(...camada);
220
+ }
221
+ }
222
+ // Nenhuma camada passou: é problema de credencial, não de campo restrito.
223
+ if (!algumaPassou)
224
+ return { ok: false, reason: 'unauthorized' };
225
+ const txt = (k) => {
226
+ const x = v[k];
227
+ return typeof x === 'string' && x.length > 0 ? x : undefined;
228
+ };
229
+ const dominios = Array.isArray(v.app_domains)
230
+ ? v.app_domains.filter((d) => typeof d === 'string')
231
+ : [];
232
+ return {
233
+ ok: true,
234
+ value: {
235
+ id: txt('id') ?? appId,
236
+ ...(txt('name') ? { name: txt('name') } : {}),
237
+ ...(txt('category') ? { category: txt('category') } : {}),
238
+ ...(txt('privacy_policy_url') ? { privacyPolicyUrl: txt('privacy_policy_url') } : {}),
239
+ ...(txt('terms_of_service_url') ? { termsOfServiceUrl: txt('terms_of_service_url') } : {}),
240
+ ...(txt('data_deletion_url')
241
+ ? { dataDeletionInstructionsUrl: txt('data_deletion_url') }
242
+ : {}),
243
+ ...(txt('deauth_callback_url') ? { deauthCallbackUrl: txt('deauth_callback_url') } : {}),
244
+ appDomains: dominios,
245
+ ...(txt('contact_email') ? { contactEmail: txt('contact_email') } : {}),
246
+ ...(txt('icon_url') ? { iconUrl: txt('icon_url') } : {}),
247
+ ...(txt('link') ? { link: txt('link') } : {}),
248
+ unreadableFields: ilegiveis,
249
+ },
250
+ };
251
+ }
252
+ //# sourceMappingURL=webhook-subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-subscription.js","sourceRoot":"","sources":["../../src/communication/webhook-subscription.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Callbacks de entrega dos canais.
3
+ *
4
+ * **Separado do webhook financeiro (Asaas), e não por organização de pastas.**
5
+ * São dois fluxos com confianças e consequências diferentes: o financeiro dá
6
+ * baixa em dinheiro, este só atualiza o que a tela mostra sobre uma mensagem.
7
+ * Misturá-los coloca um endpoint que qualquer provedor de mensagem pode chamar
8
+ * no mesmo caminho de código que movimenta valor.
9
+ *
10
+ * O que este módulo faz: traduzir o vocabulário de cada provider para os estados
11
+ * de `status.ts`, e devolver a referência que localiza a ação. O que ele NÃO
12
+ * faz: autenticar (é da borda HTTP) e escrever no banco (é do consumidor).
13
+ */
14
+ import type { ChannelKey } from './channel.js';
15
+ import { type WebhookOrigin } from './routing.js';
16
+ import { type DeliveryStatus } from './status.js';
17
+ export interface DeliveryEvent {
18
+ channel: ChannelKey;
19
+ /** Identificador da mensagem no provider — a única via de acesso à ação. */
20
+ providerRef: string;
21
+ status: DeliveryStatus;
22
+ occurredAt: string;
23
+ /** Motivo, quando o provider informa falha. Nunca PII, nunca segredo. */
24
+ code?: string;
25
+ detail?: string;
26
+ }
27
+ export interface MetaStatusEntry {
28
+ id?: string;
29
+ status?: string;
30
+ timestamp?: string;
31
+ errors?: {
32
+ code?: number;
33
+ title?: string;
34
+ }[];
35
+ }
36
+ /**
37
+ * Normaliza o corpo do webhook da Meta.
38
+ *
39
+ * Devolve lista porque a Meta entrega em LOTE: um POST traz vários status, de
40
+ * várias mensagens. Ler só o primeiro perde os demais em silêncio — o mesmo
41
+ * defeito de forma que o GA4 já ensinou nesta casa
42
+ * (`feedback_ga4_batches_events_in_post_body`).
43
+ */
44
+ export declare function parseMetaDeliveryWebhook(body: unknown, origin?: WebhookOrigin): DeliveryEvent[];
45
+ /**
46
+ * As origens DISTINTAS declaradas num corpo de webhook.
47
+ *
48
+ * O consumidor roteia cada uma separadamente. Recusar o POST inteiro porque uma
49
+ * das contas é desconhecida descartaria os eventos legítimos das outras; aceitar
50
+ * tudo sob a primeira origem seria pior.
51
+ */
52
+ export declare function parseMetaWebhookOrigins(body: unknown): WebhookOrigin[];
53
+ export type WebhookApplication = {
54
+ apply: true;
55
+ status: DeliveryStatus;
56
+ } | {
57
+ apply: false;
58
+ reason: 'not_reported_by_channel' | 'no_progress';
59
+ };
60
+ /**
61
+ * O evento deve ser gravado?
62
+ *
63
+ * Duas recusas distintas. `not_reported_by_channel` é defesa contra equivalência
64
+ * falsa: um `read` chegando por um canal que não reporta leitura é dado
65
+ * inventado — e gravá-lo faria a tela afirmar que o cliente LEU uma cobrança
66
+ * que ninguém sabe se ele leu.
67
+ *
68
+ * `no_progress` é a chegada fora de ordem, que acontece o tempo todo: um
69
+ * `delivered` depois de um `read` já registrado não pode "desler" a mensagem.
70
+ */
71
+ export declare function applyDeliveryEvent(current: DeliveryStatus, event: DeliveryEvent): WebhookApplication;
72
+ /**
73
+ * Verificação do handshake de assinatura da Meta (`GET` com `hub.*`).
74
+ *
75
+ * Devolve o desafio a ecoar, ou `null`. **`null` é a resposta certa para token
76
+ * errado, token ausente e segredo não configurado** — os três.
77
+ *
78
+ * O caso "segredo não configurado" é o que já custou caro: um webhook do Manga
79
+ * Verde ecoava o desafio mesmo com token inválido, e ficou aberto em produção.
80
+ * Um endpoint que confirma a inscrição sem conferir nada entrega à Meta um
81
+ * caminho pelo qual qualquer um assina os eventos daquela WABA. Aqui a ausência
82
+ * de segredo falha FECHADA.
83
+ */
84
+ export declare function verifyMetaChallenge(query: Record<string, string | undefined>, expectedVerifyToken: string | undefined): string | null;
85
+ /**
86
+ * Assinatura `X-Hub-Signature-256` da Meta: `sha256=<hmac hex do corpo bruto>`.
87
+ *
88
+ * O corpo tem de ser o BRUTO, byte a byte. Reserializar o JSON parseado muda
89
+ * espaços e ordem de chaves e faz a assinatura de um payload legítimo falhar —
90
+ * o que empurra quem depura para desligar a verificação "porque não funciona".
91
+ */
92
+ export declare function verifyMetaSignature(rawBody: string | Buffer, signatureHeader: string | undefined, appSecret: string | undefined): boolean;
93
+ /**
94
+ * Identificador do evento para deduplicação.
95
+ *
96
+ * A Meta não manda id de evento — manda o id da MENSAGEM e um estado. Dois
97
+ * callbacks distintos da mesma mensagem (`delivered` e depois `read`) são
98
+ * eventos diferentes e precisam passar os dois; o mesmo callback reentregue
99
+ * precisa ser barrado. `providerRef:status` é exatamente essa fronteira.
100
+ *
101
+ * O timestamp fica FORA de propósito: a Meta reenvia o mesmo evento com o mesmo
102
+ * timestamp, mas um reenvio com relógio diferente passaria pelo dedup e
103
+ * duplicaria a linha de trilha.
104
+ */
105
+ export declare function deliveryEventId(event: DeliveryEvent): string;
106
+ export interface InboundOptOut {
107
+ channel: ChannelKey;
108
+ /** Telefone em E.164 como o provider entregou. Quem traduz para cliente é o produto. */
109
+ from: string;
110
+ occurredAt: string;
111
+ }
112
+ /**
113
+ * Respostas de opt-out numa entrega da Meta.
114
+ *
115
+ * Separado de `parseMetaDeliveryWebhook` porque são fatos de natureza diferente:
116
+ * um descreve o que aconteceu com uma mensagem NOSSA, o outro é uma manifestação
117
+ * do cliente. Misturá-los faria um `DeliveryEvent` carregar um telefone — e a
118
+ * trilha de entrega deixaria de poder ser exibida sem expor contato.
119
+ */
120
+ export declare function parseMetaInboundOptOut(body: unknown, origin?: WebhookOrigin): InboundOptOut[];
121
+ //# sourceMappingURL=webhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/communication/webhook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,UAAU,CAAC;IACpB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9C;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE,CAoC/F;AA8DD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,EAAE,CAOtE;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GACvC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,yBAAyB,GAAG,aAAa,CAAA;CAAE,CAAC;AAExE;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,aAAa,GACnB,kBAAkB,CAOpB;AASD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACzC,mBAAmB,EAAE,MAAM,GAAG,SAAS,GACtC,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAUT;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAE5D;AAaD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,UAAU,CAAC;IACpB,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE,CA+B7F"}
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Callbacks de entrega dos canais.
3
+ *
4
+ * **Separado do webhook financeiro (Asaas), e não por organização de pastas.**
5
+ * São dois fluxos com confianças e consequências diferentes: o financeiro dá
6
+ * baixa em dinheiro, este só atualiza o que a tela mostra sobre uma mensagem.
7
+ * Misturá-los coloca um endpoint que qualquer provedor de mensagem pode chamar
8
+ * no mesmo caminho de código que movimenta valor.
9
+ *
10
+ * O que este módulo faz: traduzir o vocabulário de cada provider para os estados
11
+ * de `status.ts`, e devolver a referência que localiza a ação. O que ele NÃO
12
+ * faz: autenticar (é da borda HTTP) e escrever no banco (é do consumidor).
13
+ */
14
+ import { createHash, createHmac, timingSafeEqual } from 'node:crypto';
15
+ import { sameOrigin } from './routing.js';
16
+ import { advanceStatus, channelReports } from './status.js';
17
+ /**
18
+ * Estados da Meta Cloud (campo `statuses[].status`).
19
+ *
20
+ * `failed` da Meta vem com `errors[]` — o motivo entra em `code`, não em
21
+ * `detail`, para que a métrica agregue por causa e não por texto.
22
+ */
23
+ const META_STATUS = {
24
+ sent: 'sent',
25
+ delivered: 'delivered',
26
+ read: 'read',
27
+ failed: 'failed',
28
+ };
29
+ /**
30
+ * Normaliza o corpo do webhook da Meta.
31
+ *
32
+ * Devolve lista porque a Meta entrega em LOTE: um POST traz vários status, de
33
+ * várias mensagens. Ler só o primeiro perde os demais em silêncio — o mesmo
34
+ * defeito de forma que o GA4 já ensinou nesta casa
35
+ * (`feedback_ga4_batches_events_in_post_body`).
36
+ */
37
+ export function parseMetaDeliveryWebhook(body, origin) {
38
+ const events = [];
39
+ forEachChange(body, (change, changeOrigin) => {
40
+ // Sob um App único do motor, um POST traz eventos de várias contas. Aplicar
41
+ // o lote inteiro no contexto de um tenant só levaria a entrega de um
42
+ // escritório para dentro da trilha de outro.
43
+ //
44
+ // Sem `origin`, o lote inteiro passa — é o caminho legado, em que a URL já
45
+ // disse de quem é. Com `origin`, um change que não declara procedência
46
+ // NUNCA casa: no caminho novo, procedência ausente é procedência
47
+ // desconhecida, e desconhecida não entra na trilha de ninguém.
48
+ if (origin && (!changeOrigin || !sameOrigin(origin, changeOrigin)))
49
+ return;
50
+ const statuses = change?.value?.statuses;
51
+ if (!Array.isArray(statuses))
52
+ return;
53
+ for (const s of statuses) {
54
+ const status = s.status ? META_STATUS[s.status] : undefined;
55
+ if (!s.id || !status)
56
+ continue;
57
+ const error = s.errors?.[0];
58
+ events.push({
59
+ channel: 'whatsapp',
60
+ providerRef: s.id,
61
+ status,
62
+ occurredAt: s.timestamp
63
+ ? new Date(Number(s.timestamp) * 1000).toISOString()
64
+ : new Date().toISOString(),
65
+ code: error?.code ? `meta_${error.code}` : undefined,
66
+ detail: error?.title?.slice(0, 200),
67
+ });
68
+ }
69
+ });
70
+ return events;
71
+ }
72
+ /**
73
+ * Percorre `entry[].changes[]` entregando, junto de cada mudança, a ORIGEM que
74
+ * ela declara.
75
+ *
76
+ * Existe para que o parser de status, o de opt-out e o de origens leiam a mesma
77
+ * estrutura pelo mesmo caminho. Três travessias independentes do mesmo payload
78
+ * seriam três oportunidades de discordarem sobre de onde veio um evento — e a
79
+ * que discordasse decidiria o tenant errado.
80
+ */
81
+ function forEachChange(body, fn) {
82
+ const entries = body?.entry;
83
+ if (!Array.isArray(entries))
84
+ return;
85
+ for (const entry of entries) {
86
+ const parentRef = text(entry?.id);
87
+ const changes = entry?.changes;
88
+ if (!Array.isArray(changes))
89
+ continue;
90
+ for (const change of changes) {
91
+ const accountRef = text(change?.value?.metadata
92
+ ?.phone_number_id);
93
+ // Sem identificador de conta não há origem — mas o change AINDA é
94
+ // entregue, com `null`.
95
+ //
96
+ // Recusá-lo aqui foi a primeira versão deste código, e ela quebrou o
97
+ // caminho legado inteiro: um payload sem `metadata` deixava de ser
98
+ // parseado e o lote virava lista vazia, em silêncio. A suíte existente
99
+ // pegou. Quem decide o que fazer com procedência ausente é o chamador —
100
+ // o legado processa, o roteado descarta.
101
+ fn(change, accountRef
102
+ ? {
103
+ provider: 'meta_whatsapp',
104
+ providerAccountRef: accountRef,
105
+ ...(parentRef ? { providerParentRef: parentRef } : {}),
106
+ }
107
+ : null);
108
+ }
109
+ }
110
+ }
111
+ function text(v) {
112
+ if (typeof v === 'string') {
113
+ const t = v.trim();
114
+ return t.length > 0 && t.length <= 120 ? t : undefined;
115
+ }
116
+ // A Meta serializa `entry.id` e `phone_number_id` como string, mas um número
117
+ // vindo de um mock ou de uma versão futura não deve virar `undefined` em
118
+ // silêncio — isso classificaria o evento como sem origem e o descartaria.
119
+ if (typeof v === 'number' && Number.isSafeInteger(v) && v > 0)
120
+ return String(v);
121
+ return undefined;
122
+ }
123
+ /**
124
+ * As origens DISTINTAS declaradas num corpo de webhook.
125
+ *
126
+ * O consumidor roteia cada uma separadamente. Recusar o POST inteiro porque uma
127
+ * das contas é desconhecida descartaria os eventos legítimos das outras; aceitar
128
+ * tudo sob a primeira origem seria pior.
129
+ */
130
+ export function parseMetaWebhookOrigins(body) {
131
+ const out = [];
132
+ forEachChange(body, (_change, origin) => {
133
+ if (!origin)
134
+ return;
135
+ if (!out.some((o) => sameOrigin(o, origin)))
136
+ out.push(origin);
137
+ });
138
+ return out;
139
+ }
140
+ /**
141
+ * O evento deve ser gravado?
142
+ *
143
+ * Duas recusas distintas. `not_reported_by_channel` é defesa contra equivalência
144
+ * falsa: um `read` chegando por um canal que não reporta leitura é dado
145
+ * inventado — e gravá-lo faria a tela afirmar que o cliente LEU uma cobrança
146
+ * que ninguém sabe se ele leu.
147
+ *
148
+ * `no_progress` é a chegada fora de ordem, que acontece o tempo todo: um
149
+ * `delivered` depois de um `read` já registrado não pode "desler" a mensagem.
150
+ */
151
+ export function applyDeliveryEvent(current, event) {
152
+ if (!channelReports(event.channel, event.status)) {
153
+ return { apply: false, reason: 'not_reported_by_channel' };
154
+ }
155
+ const next = advanceStatus(current, event.status);
156
+ if (next === current)
157
+ return { apply: false, reason: 'no_progress' };
158
+ return { apply: true, status: next };
159
+ }
160
+ /* ── Autenticação da borda ─────────────────────────────────────────────────
161
+ *
162
+ * Mora aqui, e não na rota, porque a comparação precisa ser de tempo constante e
163
+ * ninguém escreve isso certo por acidente. O que a rota faz é passar o corpo
164
+ * BRUTO e os cabeçalhos; o que este módulo faz é dizer sim ou não.
165
+ */
166
+ /**
167
+ * Verificação do handshake de assinatura da Meta (`GET` com `hub.*`).
168
+ *
169
+ * Devolve o desafio a ecoar, ou `null`. **`null` é a resposta certa para token
170
+ * errado, token ausente e segredo não configurado** — os três.
171
+ *
172
+ * O caso "segredo não configurado" é o que já custou caro: um webhook do Manga
173
+ * Verde ecoava o desafio mesmo com token inválido, e ficou aberto em produção.
174
+ * Um endpoint que confirma a inscrição sem conferir nada entrega à Meta um
175
+ * caminho pelo qual qualquer um assina os eventos daquela WABA. Aqui a ausência
176
+ * de segredo falha FECHADA.
177
+ */
178
+ export function verifyMetaChallenge(query, expectedVerifyToken) {
179
+ if (!expectedVerifyToken)
180
+ return null;
181
+ if (query['hub.mode'] !== 'subscribe')
182
+ return null;
183
+ const provided = query['hub.verify_token'];
184
+ const challenge = query['hub.challenge'];
185
+ if (!provided || !challenge)
186
+ return null;
187
+ if (!timingSafeEqualString(provided, expectedVerifyToken))
188
+ return null;
189
+ return challenge;
190
+ }
191
+ /**
192
+ * Assinatura `X-Hub-Signature-256` da Meta: `sha256=<hmac hex do corpo bruto>`.
193
+ *
194
+ * O corpo tem de ser o BRUTO, byte a byte. Reserializar o JSON parseado muda
195
+ * espaços e ordem de chaves e faz a assinatura de um payload legítimo falhar —
196
+ * o que empurra quem depura para desligar a verificação "porque não funciona".
197
+ */
198
+ export function verifyMetaSignature(rawBody, signatureHeader, appSecret) {
199
+ if (!appSecret || !signatureHeader)
200
+ return false;
201
+ const [algo, provided] = signatureHeader.split('=');
202
+ if (algo !== 'sha256' || !provided)
203
+ return false;
204
+ const expected = createHmac('sha256', appSecret)
205
+ .update(typeof rawBody === 'string' ? Buffer.from(rawBody, 'utf8') : rawBody)
206
+ .digest('hex');
207
+ return timingSafeEqualString(provided, expected);
208
+ }
209
+ /**
210
+ * Comparação de tempo constante sobre strings.
211
+ *
212
+ * `timingSafeEqual` lança quando os buffers têm tamanhos diferentes — e o
213
+ * tamanho já é informação. Por isso os dois lados são reduzidos a um digest de
214
+ * tamanho fixo antes da comparação: o atacante não aprende nem o conteúdo nem o
215
+ * comprimento.
216
+ */
217
+ function timingSafeEqualString(a, b) {
218
+ const da = createHash('sha256').update(a, 'utf8').digest();
219
+ const db = createHash('sha256').update(b, 'utf8').digest();
220
+ return timingSafeEqual(da, db);
221
+ }
222
+ /**
223
+ * Identificador do evento para deduplicação.
224
+ *
225
+ * A Meta não manda id de evento — manda o id da MENSAGEM e um estado. Dois
226
+ * callbacks distintos da mesma mensagem (`delivered` e depois `read`) são
227
+ * eventos diferentes e precisam passar os dois; o mesmo callback reentregue
228
+ * precisa ser barrado. `providerRef:status` é exatamente essa fronteira.
229
+ *
230
+ * O timestamp fica FORA de propósito: a Meta reenvia o mesmo evento com o mesmo
231
+ * timestamp, mas um reenvio com relógio diferente passaria pelo dedup e
232
+ * duplicaria a linha de trilha.
233
+ */
234
+ export function deliveryEventId(event) {
235
+ return `${event.providerRef}:${event.status}`;
236
+ }
237
+ /**
238
+ * Palavras que o destinatário usa para pedir silêncio.
239
+ *
240
+ * Fechada e curta de propósito. Uma lista generosa transforma "pare de me
241
+ * cobrar tanto" — uma reclamação, não um opt-out — em bloqueio permanente do
242
+ * canal; e o opt-out registrado por `customer_reply` é justamente o que ninguém
243
+ * no escritório pode reverter. Errar para o lado de não registrar é recuperável
244
+ * (o cliente repete); errar para o outro lado, não.
245
+ */
246
+ const OPT_OUT_WORDS = new Set(['sair', 'parar', 'pare', 'stop', 'descadastrar', 'cancelar']);
247
+ /**
248
+ * Respostas de opt-out numa entrega da Meta.
249
+ *
250
+ * Separado de `parseMetaDeliveryWebhook` porque são fatos de natureza diferente:
251
+ * um descreve o que aconteceu com uma mensagem NOSSA, o outro é uma manifestação
252
+ * do cliente. Misturá-los faria um `DeliveryEvent` carregar um telefone — e a
253
+ * trilha de entrega deixaria de poder ser exibida sem expor contato.
254
+ */
255
+ export function parseMetaInboundOptOut(body, origin) {
256
+ const out = [];
257
+ forEachChange(body, (change, changeOrigin) => {
258
+ if (origin && (!changeOrigin || !sameOrigin(origin, changeOrigin)))
259
+ return;
260
+ const messages = change?.value?.messages;
261
+ if (!Array.isArray(messages))
262
+ return;
263
+ for (const m of messages) {
264
+ const body = m.text?.body?.trim().toLowerCase();
265
+ if (!m.from || !body)
266
+ continue;
267
+ // Palavra ISOLADA. "não quero parar de receber" contém "parar" e é o
268
+ // oposto de um opt-out; casar por inclusão registraria o contrário do
269
+ // que o cliente pediu.
270
+ if (!OPT_OUT_WORDS.has(body))
271
+ continue;
272
+ out.push({
273
+ channel: 'whatsapp',
274
+ from: m.from,
275
+ occurredAt: m.timestamp
276
+ ? new Date(Number(m.timestamp) * 1000).toISOString()
277
+ : new Date().toISOString(),
278
+ });
279
+ }
280
+ });
281
+ return out;
282
+ }
283
+ //# sourceMappingURL=webhook.js.map