@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
@@ -1,4 +1,33 @@
1
- import { NotFoundError, uuidv7 } from '@baruk/shared';
1
+ import { ConflictError, NotFoundError, uuidv7 } from '@baruk/shared';
2
+ import { toE164OrNull } from '../contacts/phone.js';
3
+ export function contactabilityOf(input) {
4
+ const email = input.email?.trim() ? 'ready' : 'missing';
5
+ const phone = input.phone?.trim() ? 'ready' : 'missing';
6
+ return { email, phone, reachable: email === 'ready' || phone === 'ready' };
7
+ }
8
+ /**
9
+ * Normalização de contato.
10
+ *
11
+ * E-mail vira minúsculo e sem espaços — a coluna é `citext`, mas quem lê o dado
12
+ * fora do banco não herda essa insensibilidade. Telefone guarda só dígitos e um
13
+ * `+` inicial: máscara é apresentação, e comparar "(62) 99999-9999" com
14
+ * "+5562999999999" é o tipo de divergência que só aparece quando a mensagem não
15
+ * chega.
16
+ */
17
+ export function normalizeEmail(v) {
18
+ const t = v?.trim().toLowerCase();
19
+ return t ? t : null;
20
+ }
21
+ export function normalizePhone(v) {
22
+ if (!v)
23
+ return null;
24
+ const trimmed = v.trim();
25
+ const plus = trimmed.startsWith('+');
26
+ const digits = trimmed.replace(/\D/g, '');
27
+ if (!digits)
28
+ return null;
29
+ return plus ? `+${digits}` : digits;
30
+ }
2
31
  function mapRow(r) {
3
32
  return {
4
33
  id: r.id,
@@ -6,30 +35,58 @@ function mapRow(r) {
6
35
  clientType: r.client_type,
7
36
  displayName: r.display_name,
8
37
  documentNumber: r.document_number,
38
+ email: r.email ?? null,
39
+ phone: r.phone ?? null,
9
40
  status: r.status,
10
41
  createdAt: r.created_at.toISOString(),
42
+ contactability: contactabilityOf({ email: r.email, phone: r.phone }),
11
43
  };
12
44
  }
45
+ /**
46
+ * Traduz a violação de documento duplicado.
47
+ *
48
+ * O banco impede dois clientes com o mesmo CPF/CNPJ no tenant — regra correta,
49
+ * e o escritório precisa saber que foi ISSO. Sem tradução, a rota devolvia 500
50
+ * genérico: quem cadastrava via um "erro interno" onde havia um cadastro já
51
+ * existente, e não tinha como descobrir.
52
+ */
53
+ function asDuplicateDocument(err) {
54
+ const e = err;
55
+ if (e?.code === '23505' && (e.constraint_name ?? '').includes('document')) {
56
+ throw new ConflictError('Já existe um cliente com este CPF/CNPJ neste escritório.');
57
+ }
58
+ }
13
59
  export async function createClient(tx, input) {
14
60
  // tenant_id vem da GUC — nunca do input. A WITH CHECK da RLS recusa qualquer
15
61
  // tentativa de gravar fora do tenant corrente.
16
- const rows = await tx `
17
- INSERT INTO client (id, tenant_id, client_type, display_name, document_number, created_by)
18
- VALUES (
19
- ${uuidv7()},
20
- current_setting('app.current_tenant')::uuid,
21
- ${input.clientType ?? 'pj'},
22
- ${input.displayName},
23
- ${input.documentNumber ?? null},
24
- ${input.createdBy ?? null}
25
- )
26
- RETURNING id, tenant_id, client_type, display_name, document_number, status, created_at
27
- `;
28
- return mapRow(rows[0]);
62
+ try {
63
+ const rows = await tx `
64
+ INSERT INTO client (id, tenant_id, client_type, display_name, document_number,
65
+ email, phone, phone_e164, created_by)
66
+ VALUES (
67
+ ${uuidv7()},
68
+ current_setting('app.current_tenant')::uuid,
69
+ ${input.clientType ?? 'pj'},
70
+ ${input.displayName},
71
+ ${input.documentNumber ?? null},
72
+ ${normalizeEmail(input.email)},
73
+ ${normalizePhone(input.phone)},
74
+ ${toE164OrNull(input.phone)},
75
+ ${input.createdBy ?? null}
76
+ )
77
+ RETURNING id, tenant_id, client_type, display_name, document_number, email, phone,
78
+ status, created_at
79
+ `;
80
+ return mapRow(rows[0]);
81
+ }
82
+ catch (err) {
83
+ asDuplicateDocument(err);
84
+ throw err;
85
+ }
29
86
  }
30
87
  export async function listClients(tx) {
31
88
  const rows = await tx `
32
- SELECT id, tenant_id, client_type, display_name, document_number, status, created_at
89
+ SELECT id, tenant_id, client_type, display_name, document_number, email, phone, status, created_at
33
90
  FROM client
34
91
  WHERE deleted_at IS NULL
35
92
  ORDER BY created_at DESC
@@ -38,7 +95,7 @@ export async function listClients(tx) {
38
95
  }
39
96
  export async function getClient(tx, id) {
40
97
  const rows = await tx `
41
- SELECT id, tenant_id, client_type, display_name, document_number, status, created_at
98
+ SELECT id, tenant_id, client_type, display_name, document_number, email, phone, status, created_at
42
99
  FROM client
43
100
  WHERE id = ${id} AND deleted_at IS NULL
44
101
  `;
@@ -64,7 +121,7 @@ export async function listClientsPaged(tx, filter = {}) {
64
121
  const offset = filter.offset ?? 0;
65
122
  const like = filter.search ? `%${filter.search}%` : null;
66
123
  const rows = await tx `
67
- SELECT id, tenant_id, client_type, display_name, document_number, status, created_at,
124
+ SELECT id, tenant_id, client_type, display_name, document_number, email, phone, status, created_at,
68
125
  count(*) OVER() AS total
69
126
  FROM client
70
127
  WHERE deleted_at IS NULL
@@ -77,14 +134,25 @@ export async function listClientsPaged(tx, filter = {}) {
77
134
  return { items: rows.map((r) => mapRow(r)), total };
78
135
  }
79
136
  export async function updateClient(tx, id, input) {
137
+ // Corrigir um documento para um que já existe cai na mesma violação — e o
138
+ // escritório precisa da mesma explicação, não de um 500.
80
139
  // Casts explícitos: parâmetros NULL sem tipo quebram COALESCE ("could not
81
140
  // determine data type of parameter") no PostgreSQL.
82
- const rows = await tx `
141
+ try {
142
+ const rows = await tx `
83
143
  UPDATE client SET
84
144
  display_name = COALESCE(${input.displayName ?? null}::text, display_name),
85
145
  legal_name = COALESCE(${input.legalName ?? null}::text, legal_name),
86
- email = COALESCE(${input.email ?? null}::citext, email),
87
- phone = COALESCE(${input.phone ?? null}::text, phone),
146
+ document_number = COALESCE(${input.documentNumber ?? null}::text, document_number),
147
+ email = COALESCE(${normalizeEmail(input.email)}::citext, email),
148
+ phone = COALESCE(${normalizePhone(input.phone)}::text, phone),
149
+ -- Derivado, nunca digitado. A coluna phone guarda o que o operador
150
+ -- escreveu e continua sendo dele; phone_e164 e a forma que os providers
151
+ -- exigem. So e recalculado quando o telefone vem no corpo: ausente
152
+ -- preserva o valor, e um telefone que nao parseia zera o canonico em vez
153
+ -- de manter um E.164 velho apontando para outro numero.
154
+ phone_e164 = CASE WHEN ${input.phone ?? null}::text IS NULL THEN phone_e164
155
+ ELSE ${toE164OrNull(input.phone)}::text END,
88
156
  status = COALESCE(${input.status ?? null}::text, status),
89
157
  updated_by = ${input.updatedBy ?? null}::uuid,
90
158
  updated_at = now(),
@@ -92,7 +160,12 @@ export async function updateClient(tx, id, input) {
92
160
  WHERE id = ${id} AND deleted_at IS NULL
93
161
  RETURNING id
94
162
  `;
95
- return rows.count;
163
+ return rows.count;
164
+ }
165
+ catch (err) {
166
+ asDuplicateDocument(err);
167
+ throw err;
168
+ }
96
169
  }
97
170
  export async function softDeleteClient(tx, id, deletedBy) {
98
171
  const rows = await tx `
@@ -1 +1 @@
1
- {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/clients/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/clients/repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import type { Tx } from '../db/client.js';
2
+ /**
3
+ * Identidade do escritório para a comunicação transacional.
4
+ *
5
+ * Mora em `tenant.settings.branding` (jsonb que já existia) — sem tabela nem
6
+ * migration. Nenhuma marca está no código: o que aparece no e-mail vem do tenant
7
+ * que está enviando, e um escritório novo entra por configuração.
8
+ *
9
+ * Os valores canônicos de cada marca vivem no **Brand OS**
10
+ * (`frameworks/brand-os/brands/<marca>/creative-engine/brand-kit.json`), que é a
11
+ * fonte de verdade da identidade. Este módulo consome; não redefine.
12
+ */
13
+ /**
14
+ * O que o asset de logo É, do ponto de vista do manual de marca.
15
+ *
16
+ * A distinção não é cosmética: um **lockup** já contém o nome do escritório
17
+ * desenhado; um **símbolo** não. Renderizar os dois do mesmo jeito ou repete o
18
+ * nome duas vezes no cabeçalho, ou deixa a mensagem sem nome quando o leitor
19
+ * bloqueia imagens. O tenant declara qual dos dois enviou.
20
+ */
21
+ export type LogoKind = 'symbol' | 'lockup';
22
+ export interface TenantBranding {
23
+ officeName: string;
24
+ /** Assinatura do rodapé; cai em `officeName` quando não definida. */
25
+ signatureName: string;
26
+ /** Frase curta da marca. Só aparece se o tenant configurar. */
27
+ tagline: string | null;
28
+ /**
29
+ * Logomarca para o cabeçalho — ou seja, o asset que fica sobre `primaryColor`.
30
+ * Um kit de marca sério tem versão clara e escura; o tenant aponta a que
31
+ * combina com o fundo que ele mesmo escolheu.
32
+ *
33
+ * Formato: PNG ou JPG em URL pública. **SVG não serve** — Gmail e Outlook não
34
+ * o renderizam em e-mail. Ausente é estado válido: o cabeçalho vira
35
+ * tipográfico, nunca uma marca inventada.
36
+ */
37
+ logoUrl: string | null;
38
+ logoKind: LogoKind;
39
+ primaryColor: string;
40
+ /** Usada em detalhes; cai na primária quando ausente. */
41
+ secondaryColor: string;
42
+ /** Destaque pontual (valor, borda do card). */
43
+ accentColor: string;
44
+ /** Fundo da página do e-mail (fora do cartão branco). */
45
+ backgroundColor: string;
46
+ /** Cor do texto corrido. */
47
+ textColor: string;
48
+ /** Cor de apoio: rodapé, rótulos, texto secundário. */
49
+ mutedColor: string;
50
+ /**
51
+ * Stack de fontes do corpo. Webfont não carrega no Outlook, então a stack
52
+ * precisa terminar em famílias que todo cliente tem — quem configurar só o
53
+ * nome da fonte da marca recebe a queda automática.
54
+ */
55
+ fontFamily: string;
56
+ supportEmail: string | null;
57
+ supportPhone: string | null;
58
+ /** Site do escritório. Corresponde ao `websiteUrl` do vocabulário de marca. */
59
+ website: string | null;
60
+ locale: 'pt-BR';
61
+ }
62
+ export declare function getTenantBranding(tx: Tx): Promise<TenantBranding>;
63
+ /**
64
+ * Remetente no formato `Nome <endereço>`.
65
+ *
66
+ * O endereço continua sendo o do domínio verificado no provider — trocá-lo
67
+ * quebraria a entrega. O que muda é o NOME exibido: as mensagens saíam como
68
+ * "Baruk Contábil" e assinavam "SC Organização Contábil", o que faz o cliente
69
+ * duvidar de quem está cobrando.
70
+ */
71
+ export declare function senderFor(branding: TenantBranding, fallbackFrom: string): string;
72
+ //# sourceMappingURL=branding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.d.ts","sourceRoot":"","sources":["../../src/collection/branding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C;;;;;;;;;;GAUG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;;;;OAQG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,eAAe,EAAE,MAAM,CAAC;IACxB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,+EAA+E;IAC/E,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AA4ED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAmDvE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAKhF"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Padrão neutro do produto — deliberadamente SEM marca.
3
+ *
4
+ * Um tenant sem branding configurado não deve herdar a identidade de outro
5
+ * escritório nem a do Baruk: o cinza-azulado abaixo não pertence a marca
6
+ * nenhuma, e é o sinal visível de que falta configurar.
7
+ */
8
+ const NEUTRAL_PRIMARY = '#2b3440';
9
+ const NEUTRAL_ACCENT = '#4a5563';
10
+ const NEUTRAL_BACKGROUND = '#eef1f4';
11
+ const NEUTRAL_TEXT = '#2b3440';
12
+ const NEUTRAL_MUTED = '#6b7684';
13
+ /** Famílias que existem em qualquer cliente de e-mail — o fim de toda stack. */
14
+ const UNIVERSAL_FALLBACK = `-apple-system,'Segoe UI',Helvetica,Arial,sans-serif`;
15
+ /**
16
+ * Cor só entra se for hex válido.
17
+ *
18
+ * O valor vem de configuração editável e é interpolado dentro de um atributo
19
+ * `style` — aceitar texto livre deixaria o tenant injetar CSS, ou fechar o
20
+ * atributo e injetar markup, na mensagem que sai em nome dele.
21
+ */
22
+ function safeColor(v, fallback) {
23
+ return typeof v === 'string' && /^#[0-9a-fA-F]{6}$/.test(v) ? v : fallback;
24
+ }
25
+ /** URL só entra se for https — evita `javascript:` e `data:` no `src`/`href`. */
26
+ function safeUrl(v) {
27
+ if (typeof v !== 'string')
28
+ return null;
29
+ return /^https:\/\/[^\s"'<>]+$/i.test(v) ? v : null;
30
+ }
31
+ /**
32
+ * Logo só entra se for uma imagem que cliente de e-mail sabe desenhar.
33
+ *
34
+ * SVG é o formato em que os kits de marca vivem — e é justamente o que Gmail e
35
+ * Outlook não renderizam em e-mail. Aceitar o SVG produziria o pior resultado
36
+ * possível: um cabeçalho vazio, sem imagem e sem o nome que o fallback teria
37
+ * escrito. Rasterize antes; aqui, entra PNG ou JPG.
38
+ */
39
+ function safeLogoUrl(v) {
40
+ const url = safeUrl(v);
41
+ if (!url)
42
+ return null;
43
+ const path = url.split(/[?#]/)[0] ?? '';
44
+ return /\.(png|jpe?g)$/i.test(path) ? url : null;
45
+ }
46
+ /**
47
+ * A stack de fontes vai para dentro de um atributo `style`.
48
+ *
49
+ * Aspas duplas, `;`, `{` e `}` deixariam o tenant fechar a declaração e escrever
50
+ * CSS próprio na mensagem que sai em nome dele. Sobram letras, dígitos, espaço,
51
+ * hífen, vírgula, ponto e aspa simples — o que um `font-family` legítimo usa.
52
+ */
53
+ function safeFontFamily(v) {
54
+ if (typeof v !== 'string')
55
+ return UNIVERSAL_FALLBACK;
56
+ const t = v.trim().slice(0, 160);
57
+ if (!t || !/^[A-Za-z0-9 ,.'-]+$/.test(t))
58
+ return UNIVERSAL_FALLBACK;
59
+ // A queda universal é acrescentada sempre: uma stack que termina numa webfont
60
+ // vira Times New Roman no Outlook, e o e-mail perde a hierarquia inteira.
61
+ return `${t},${UNIVERSAL_FALLBACK}`;
62
+ }
63
+ function safeLogoKind(v) {
64
+ return v === 'lockup' ? 'lockup' : 'symbol';
65
+ }
66
+ function safeText(v, max = 160) {
67
+ if (typeof v !== 'string')
68
+ return null;
69
+ const t = v.trim().slice(0, max);
70
+ return t ? t : null;
71
+ }
72
+ export async function getTenantBranding(tx) {
73
+ /*
74
+ * O tenant CORRENTE, e não "o primeiro que aparecer".
75
+ *
76
+ * A consulta era `SELECT display_name, settings FROM tenant LIMIT 1`, sem
77
+ * `WHERE`. Parecia segura porque toda leitura tenant-scoped deste produto
78
+ * passa por `withContext` — mas `tenant` é a tabela RAIZ e **não tem RLS**:
79
+ * ela é a fonte da própria fronteira, não uma linha protegida por ela. Sem
80
+ * `WHERE`, a política que protege todas as outras tabelas não protege esta, e
81
+ * o `LIMIT 1` devolve um escritório arbitrário.
82
+ *
83
+ * A consequência é a pior possível para uma régua de cobrança: o e-mail sai
84
+ * com o nome, a logomarca e as cores de OUTRO escritório. Nunca apareceu
85
+ * porque a base de produção tem um tenant operando — ou seja, o defeito estava
86
+ * esperando o segundo cliente.
87
+ *
88
+ * Sem contexto de tenant a consulta devolve zero linhas de propósito, e o
89
+ * branding cai no padrão NEUTRO — que não pertence a marca nenhuma. Um default
90
+ * que herda a marca do vizinho é o defeito, não o conserto.
91
+ */
92
+ const rows = await tx `
93
+ SELECT display_name, settings FROM tenant
94
+ WHERE id = NULLIF(current_setting('app.current_tenant', true), '')::uuid
95
+ LIMIT 1
96
+ `;
97
+ const row = rows[0];
98
+ const raw = (row?.settings?.branding ?? {});
99
+ const officeName = safeText(raw.officeName) ?? row?.display_name ?? 'Seu escritório contábil';
100
+ const primary = safeColor(raw.primaryColor, NEUTRAL_PRIMARY);
101
+ return {
102
+ officeName,
103
+ signatureName: safeText(raw.signatureName) ?? officeName,
104
+ tagline: safeText(raw.tagline, 120),
105
+ logoUrl: safeLogoUrl(raw.logoUrl),
106
+ logoKind: safeLogoKind(raw.logoKind),
107
+ primaryColor: primary,
108
+ // Secundária cai na primária: um tenant que configurou só uma cor fica
109
+ // coerente, em vez de ganhar um segundo tom que ninguém escolheu.
110
+ secondaryColor: safeColor(raw.secondaryColor, primary),
111
+ accentColor: safeColor(raw.accentColor, NEUTRAL_ACCENT),
112
+ backgroundColor: safeColor(raw.backgroundColor, NEUTRAL_BACKGROUND),
113
+ textColor: safeColor(raw.textColor, NEUTRAL_TEXT),
114
+ mutedColor: safeColor(raw.mutedColor, NEUTRAL_MUTED),
115
+ fontFamily: safeFontFamily(raw.fontFamily),
116
+ supportEmail: safeText(raw.supportEmail, 120),
117
+ supportPhone: safeText(raw.supportPhone, 40),
118
+ website: safeUrl(raw.website),
119
+ locale: 'pt-BR',
120
+ };
121
+ }
122
+ /**
123
+ * Remetente no formato `Nome <endereço>`.
124
+ *
125
+ * O endereço continua sendo o do domínio verificado no provider — trocá-lo
126
+ * quebraria a entrega. O que muda é o NOME exibido: as mensagens saíam como
127
+ * "Baruk Contábil" e assinavam "SC Organização Contábil", o que faz o cliente
128
+ * duvidar de quem está cobrando.
129
+ */
130
+ export function senderFor(branding, fallbackFrom) {
131
+ const address = /<([^>]+)>/.exec(fallbackFrom)?.[1] ?? fallbackFrom;
132
+ // Aspas e `<` no nome quebrariam o cabeçalho do e-mail.
133
+ const name = branding.officeName.replace(/["<>\\]/g, '').trim();
134
+ return name ? `${name} <${address}>` : fallbackFrom;
135
+ }
136
+ //# sourceMappingURL=branding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.js","sourceRoot":"","sources":["../../src/collection/branding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Contas de canal do escritório, para o motor compartilhado.
3
+ *
4
+ * Moram em `tenant.settings.channels` (jsonb que já existia) — sem tabela nem
5
+ * migration, pela mesma razão que o branding mora lá: o Office resolve
6
+ * configuração de tenant por esse caminho, e um segundo mecanismo para a mesma
7
+ * coisa é uma divergência esperando acontecer.
8
+ *
9
+ * **Nenhum valor de credencial passa por aqui.** O que o tenant configura é o
10
+ * NOME lógico do segredo no cofre (`credentialRef`); quem resolve o valor é a
11
+ * borda do adapter, com o resolvedor que o processo injeta.
12
+ */
13
+ import type { Tx } from '../db/client.js';
14
+ import type { ChannelAccountStore, SenderFallbackPolicy } from '../communication/index.js';
15
+ import type { TenantBranding } from './branding.js';
16
+ /**
17
+ * Store de contas do tenant corrente.
18
+ *
19
+ * **A amarra é a GUC da sessão, não o parâmetro.**
20
+ *
21
+ * A versão anterior consultava `WHERE id = ctx.tenantId` e depois comparava
22
+ * `row.id !== ctx.tenantId` — uma comparação que nunca pode falhar, porque o
23
+ * `WHERE` já usou o mesmo valor. Ela parecia ser a tranca contra "pedir o tenant
24
+ * errado dentro da transação certa" e não era nenhuma tranca: bastava um
25
+ * chamador passar um contexto alheio para ler a configuração de canal de outro
26
+ * escritório, `credentialRef` inclusive.
27
+ *
28
+ * `tenant` é a tabela RAIZ e não tem RLS — ela define a fronteira, não é
29
+ * protegida por ela —, então a política que cobre todas as outras tabelas não
30
+ * cobria esta consulta. A correção é exigir que o tenant PEDIDO seja o mesmo da
31
+ * sessão: quem quiser ler a configuração de outro escritório precisa abrir a
32
+ * transação dele, que é justamente o que a fronteira significa.
33
+ */
34
+ export declare function createTenantChannelAccountStore(tx: Tx): ChannelAccountStore;
35
+ /**
36
+ * Fallback de plataforma da cobrança — **e-mail apenas**.
37
+ *
38
+ * Existe porque a SC já entrega e-mail em produção hoje pela chave da
39
+ * plataforma, e desligar isso para exigir configuração por escritório pararia a
40
+ * régua de quem está cobrando agora. Removê-lo não é hardening, é interrupção de
41
+ * serviço.
42
+ *
43
+ * O que muda em relação ao que o Codex reprovou é o que sai na mensagem: o NOME
44
+ * exibido passa a ser o do escritório que está cobrando, sempre. O endereço
45
+ * continua sendo o do domínio verificado — trocá-lo quebraria a entrega —, mas
46
+ * quem lê vê "SC Organização Contábil", não uma marca alheia.
47
+ *
48
+ * Nada de WhatsApp nem SMS aqui, e a proibição não é por omissão: o motor recusa
49
+ * fallback nesses canais por construção (`sender-profile.ts`). Um número de
50
+ * telefone compartilhado entre marcas é o caminho para uma marca ser bloqueada
51
+ * pelo comportamento de outra.
52
+ */
53
+ export declare function collectionSenderFallback(branding: TenantBranding, platformEmail: {
54
+ senderId: string;
55
+ credentialRef: string;
56
+ }): SenderFallbackPolicy;
57
+ //# sourceMappingURL=channel-accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-accounts.d.ts","sourceRoot":"","sources":["../../src/collection/channel-accounts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,EAEV,mBAAmB,EAEnB,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAuCpD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,+BAA+B,CAAC,EAAE,EAAE,EAAE,GAAG,mBAAmB,CA2C3E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,cAAc,EACxB,aAAa,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACzD,oBAAoB,CAatB"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Contas de canal do escritório, para o motor compartilhado.
3
+ *
4
+ * Moram em `tenant.settings.channels` (jsonb que já existia) — sem tabela nem
5
+ * migration, pela mesma razão que o branding mora lá: o Office resolve
6
+ * configuração de tenant por esse caminho, e um segundo mecanismo para a mesma
7
+ * coisa é uma divergência esperando acontecer.
8
+ *
9
+ * **Nenhum valor de credencial passa por aqui.** O que o tenant configura é o
10
+ * NOME lógico do segredo no cofre (`credentialRef`); quem resolve o valor é a
11
+ * borda do adapter, com o resolvedor que o processo injeta.
12
+ */
13
+ import { SC_PRODUCT } from './communication-bridge.js';
14
+ const STATUSES = new Set(['not_configured', 'pending_validation', 'active', 'paused', 'error']);
15
+ function text(v, max = 200) {
16
+ if (typeof v !== 'string')
17
+ return undefined;
18
+ const t = v.trim();
19
+ return t && t.length <= max ? t : undefined;
20
+ }
21
+ /**
22
+ * Metadados sem segredo, e a checagem é por ALLOWLIST de chave.
23
+ *
24
+ * Filtrar por "o que parece segredo" deixaria passar o que não parece — e o
25
+ * `meta` de um canal é jsonb editável por quem configura o tenant, então
26
+ * qualquer coisa pode ter sido colada ali. Só o que o adapter precisa entra.
27
+ */
28
+ const META_ALLOWED = new Set(['phoneNumberId', 'wabaId', 'businessId', 'region']);
29
+ function meta(v) {
30
+ if (typeof v !== 'object' || v === null)
31
+ return undefined;
32
+ const out = {};
33
+ for (const [k, raw] of Object.entries(v)) {
34
+ if (!META_ALLOWED.has(k))
35
+ continue;
36
+ const value = text(raw, 120);
37
+ if (value)
38
+ out[k] = value;
39
+ }
40
+ return Object.keys(out).length > 0 ? out : undefined;
41
+ }
42
+ /**
43
+ * Store de contas do tenant corrente.
44
+ *
45
+ * **A amarra é a GUC da sessão, não o parâmetro.**
46
+ *
47
+ * A versão anterior consultava `WHERE id = ctx.tenantId` e depois comparava
48
+ * `row.id !== ctx.tenantId` — uma comparação que nunca pode falhar, porque o
49
+ * `WHERE` já usou o mesmo valor. Ela parecia ser a tranca contra "pedir o tenant
50
+ * errado dentro da transação certa" e não era nenhuma tranca: bastava um
51
+ * chamador passar um contexto alheio para ler a configuração de canal de outro
52
+ * escritório, `credentialRef` inclusive.
53
+ *
54
+ * `tenant` é a tabela RAIZ e não tem RLS — ela define a fronteira, não é
55
+ * protegida por ela —, então a política que cobre todas as outras tabelas não
56
+ * cobria esta consulta. A correção é exigir que o tenant PEDIDO seja o mesmo da
57
+ * sessão: quem quiser ler a configuração de outro escritório precisa abrir a
58
+ * transação dele, que é justamente o que a fronteira significa.
59
+ */
60
+ export function createTenantChannelAccountStore(tx) {
61
+ return {
62
+ async find(ctx, channel) {
63
+ if (ctx.product !== SC_PRODUCT)
64
+ return null;
65
+ const rows = await tx `
66
+ SELECT id, settings FROM tenant
67
+ WHERE id = ${ctx.tenantId}
68
+ AND id = NULLIF(current_setting('app.current_tenant', true), '')::uuid
69
+ LIMIT 1
70
+ `;
71
+ const row = rows[0];
72
+ if (!row)
73
+ return null;
74
+ const channels = (row.settings?.channels ?? {});
75
+ const raw = channels[channel];
76
+ if (!raw)
77
+ return null;
78
+ const senderId = text(raw.senderId);
79
+ const credentialRef = text(raw.credentialRef);
80
+ // Sem remetente ou sem referência de credencial não há conta utilizável.
81
+ // Devolver uma conta pela metade faria o motor tentar e o provider recusar,
82
+ // gastando uma tentativa da régua para descobrir o que já se sabia aqui.
83
+ if (!senderId || !credentialRef)
84
+ return null;
85
+ const status = text(raw.status);
86
+ return {
87
+ channel,
88
+ tenantId: ctx.tenantId,
89
+ product: ctx.product,
90
+ brand: ctx.brand,
91
+ senderId,
92
+ displayName: text(raw.displayName, 120),
93
+ credentialRef,
94
+ // Estado desconhecido nunca vira `active`: configuração que ninguém
95
+ // reconhece não autoriza envio.
96
+ status: status && STATUSES.has(status) ? status : 'not_configured',
97
+ meta: meta(raw.meta),
98
+ };
99
+ },
100
+ };
101
+ }
102
+ /**
103
+ * Fallback de plataforma da cobrança — **e-mail apenas**.
104
+ *
105
+ * Existe porque a SC já entrega e-mail em produção hoje pela chave da
106
+ * plataforma, e desligar isso para exigir configuração por escritório pararia a
107
+ * régua de quem está cobrando agora. Removê-lo não é hardening, é interrupção de
108
+ * serviço.
109
+ *
110
+ * O que muda em relação ao que o Codex reprovou é o que sai na mensagem: o NOME
111
+ * exibido passa a ser o do escritório que está cobrando, sempre. O endereço
112
+ * continua sendo o do domínio verificado — trocá-lo quebraria a entrega —, mas
113
+ * quem lê vê "SC Organização Contábil", não uma marca alheia.
114
+ *
115
+ * Nada de WhatsApp nem SMS aqui, e a proibição não é por omissão: o motor recusa
116
+ * fallback nesses canais por construção (`sender-profile.ts`). Um número de
117
+ * telefone compartilhado entre marcas é o caminho para uma marca ser bloqueada
118
+ * pelo comportamento de outra.
119
+ */
120
+ export function collectionSenderFallback(branding, platformEmail) {
121
+ // O endereço vem do remetente base configurado; `senderFor` já sabe extrair só
122
+ // o endereço de um `Nome <end@dominio>`.
123
+ const address = /<([^>]+)>/.exec(platformEmail.senderId)?.[1] ?? platformEmail.senderId;
124
+ const displayName = branding.officeName.replace(/["<>\\]/g, '').trim() || undefined;
125
+ return {
126
+ email: {
127
+ senderId: address,
128
+ credentialRef: platformEmail.credentialRef,
129
+ displayNameFor: () => displayName,
130
+ },
131
+ };
132
+ }
133
+ //# sourceMappingURL=channel-accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-accounts.js","sourceRoot":"","sources":["../../src/collection/channel-accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Vocabulário de canal da régua de cobrança.
3
+ *
4
+ * **Só o vocabulário.** Este arquivo já carregou uma abstração de canal inteira
5
+ * — `CollectionChannel`, `CollectionMessage`, `resolveChannel` e um adapter de
6
+ * e-mail — e foi por ela que a cobrança tinha um SEGUNDO caminho de envio,
7
+ * paralelo ao motor compartilhado, com idempotência própria que não era gravada
8
+ * em lugar nenhum. Cron e rota manual usavam vias diferentes e não se
9
+ * enxergavam.
10
+ *
11
+ * O caminho de entrega agora é um só: `communication/`. O que restou aqui é o
12
+ * nome do canal que a política do escritório declara por etapa, que é dado de
13
+ * régua e não tem nada a ver com provider.
14
+ */
15
+ /**
16
+ * Canal declarado por etapa da régua.
17
+ *
18
+ * Subconjunto de `ChannelKey` do motor. `sms` ainda não aparece porque a régua
19
+ * não tem como declará-lo hoje — está registrado como dívida não bloqueante, e
20
+ * alargar o tipo sem alargar a validação da política gravaria passo que o motor
21
+ * aceita e a tela não sabe exibir.
22
+ */
23
+ export type CollectionChannelKey = 'email' | 'whatsapp' | 'notification';
24
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/collection/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,UAAU,GAAG,cAAc,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Vocabulário de canal da régua de cobrança.
3
+ *
4
+ * **Só o vocabulário.** Este arquivo já carregou uma abstração de canal inteira
5
+ * — `CollectionChannel`, `CollectionMessage`, `resolveChannel` e um adapter de
6
+ * e-mail — e foi por ela que a cobrança tinha um SEGUNDO caminho de envio,
7
+ * paralelo ao motor compartilhado, com idempotência própria que não era gravada
8
+ * em lugar nenhum. Cron e rota manual usavam vias diferentes e não se
9
+ * enxergavam.
10
+ *
11
+ * O caminho de entrega agora é um só: `communication/`. O que restou aqui é o
12
+ * nome do canal que a política do escritório declara por etapa, que é dado de
13
+ * régua e não tem nada a ver com provider.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=channel.js.map