@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.
- package/.baruk-provenance.json +10 -0
- package/CHANGELOG.md +85 -0
- package/dist/auth/password-reset.d.ts +30 -1
- package/dist/auth/password-reset.d.ts.map +1 -1
- package/dist/auth/password-reset.js +139 -11
- package/dist/auth/password-reset.js.map +1 -1
- package/dist/auth/service.d.ts +39 -2
- package/dist/auth/service.d.ts.map +1 -1
- package/dist/auth/service.js +75 -10
- package/dist/auth/service.js.map +1 -1
- package/dist/billing/ar-repository.d.ts +334 -0
- package/dist/billing/ar-repository.d.ts.map +1 -0
- package/dist/billing/ar-repository.js +707 -0
- package/dist/billing/ar-repository.js.map +1 -0
- package/dist/billing/auto-generation.d.ts +87 -0
- package/dist/billing/auto-generation.d.ts.map +1 -0
- package/dist/billing/auto-generation.js +181 -0
- package/dist/billing/auto-generation.js.map +1 -0
- package/dist/billing/live-guard.d.ts +64 -0
- package/dist/billing/live-guard.d.ts.map +1 -0
- package/dist/billing/live-guard.js +68 -0
- package/dist/billing/live-guard.js.map +1 -0
- package/dist/billing/payment-means-catalog.d.ts +17 -0
- package/dist/billing/payment-means-catalog.d.ts.map +1 -0
- package/dist/billing/payment-means-catalog.js +21 -0
- package/dist/billing/payment-means-catalog.js.map +1 -0
- package/dist/billing/payment-means.d.ts +38 -0
- package/dist/billing/payment-means.d.ts.map +1 -0
- package/dist/billing/payment-means.js +29 -0
- package/dist/billing/payment-means.js.map +1 -0
- package/dist/billing/payment-rail.d.ts +118 -0
- package/dist/billing/payment-rail.d.ts.map +1 -0
- package/dist/billing/payment-rail.js +295 -0
- package/dist/billing/payment-rail.js.map +1 -0
- package/dist/billing/provider/asaas.d.ts +46 -1
- package/dist/billing/provider/asaas.d.ts.map +1 -1
- package/dist/billing/provider/asaas.js +194 -14
- package/dist/billing/provider/asaas.js.map +1 -1
- package/dist/billing/provider/manual.js +1 -1
- package/dist/billing/provider/manual.js.map +1 -1
- package/dist/billing/provider/types.d.ts +115 -8
- package/dist/billing/provider/types.d.ts.map +1 -1
- package/dist/billing/provider-account.d.ts +89 -0
- package/dist/billing/provider-account.d.ts.map +1 -0
- package/dist/billing/provider-account.js +161 -0
- package/dist/billing/provider-account.js.map +1 -0
- package/dist/billing/provider-onboarding.d.ts +67 -0
- package/dist/billing/provider-onboarding.d.ts.map +1 -0
- package/dist/billing/provider-onboarding.js +234 -0
- package/dist/billing/provider-onboarding.js.map +1 -0
- package/dist/billing/receivable.d.ts +5 -1
- package/dist/billing/receivable.d.ts.map +1 -1
- package/dist/billing/reconcile.d.ts +58 -0
- package/dist/billing/reconcile.d.ts.map +1 -0
- package/dist/billing/reconcile.js +138 -0
- package/dist/billing/reconcile.js.map +1 -0
- package/dist/billing/repository.d.ts +90 -1
- package/dist/billing/repository.d.ts.map +1 -1
- package/dist/billing/repository.js +148 -19
- package/dist/billing/repository.js.map +1 -1
- package/dist/cjs/auth/password-reset.js +141 -11
- package/dist/cjs/auth/password-reset.js.map +1 -1
- package/dist/cjs/auth/service.js +75 -9
- package/dist/cjs/auth/service.js.map +1 -1
- package/dist/cjs/billing/ar-repository.js +728 -0
- package/dist/cjs/billing/ar-repository.js.map +1 -0
- package/dist/cjs/billing/auto-generation.js +186 -0
- package/dist/cjs/billing/auto-generation.js.map +1 -0
- package/dist/cjs/billing/live-guard.js +72 -0
- package/dist/cjs/billing/live-guard.js.map +1 -0
- package/dist/cjs/billing/payment-means-catalog.js +25 -0
- package/dist/cjs/billing/payment-means-catalog.js.map +1 -0
- package/dist/cjs/billing/payment-means.js +33 -0
- package/dist/cjs/billing/payment-means.js.map +1 -0
- package/dist/cjs/billing/payment-rail.js +301 -0
- package/dist/cjs/billing/payment-rail.js.map +1 -0
- package/dist/cjs/billing/provider/asaas.js +194 -14
- package/dist/cjs/billing/provider/asaas.js.map +1 -1
- package/dist/cjs/billing/provider/manual.js +1 -1
- package/dist/cjs/billing/provider/manual.js.map +1 -1
- package/dist/cjs/billing/provider-account.js +170 -0
- package/dist/cjs/billing/provider-account.js.map +1 -0
- package/dist/cjs/billing/provider-onboarding.js +239 -0
- package/dist/cjs/billing/provider-onboarding.js.map +1 -0
- package/dist/cjs/billing/reconcile.js +143 -0
- package/dist/cjs/billing/reconcile.js.map +1 -0
- package/dist/cjs/billing/repository.js +150 -18
- package/dist/cjs/billing/repository.js.map +1 -1
- package/dist/cjs/clients/repository.js +96 -20
- package/dist/cjs/clients/repository.js.map +1 -1
- package/dist/cjs/collection/branding.js +140 -0
- package/dist/cjs/collection/branding.js.map +1 -0
- package/dist/cjs/collection/channel-accounts.js +137 -0
- package/dist/cjs/collection/channel-accounts.js.map +1 -0
- package/dist/cjs/collection/channel.js +17 -0
- package/dist/cjs/collection/channel.js.map +1 -0
- package/dist/cjs/collection/communication-bridge.js +140 -0
- package/dist/cjs/collection/communication-bridge.js.map +1 -0
- package/dist/cjs/collection/communication-runtime.js +193 -0
- package/dist/cjs/collection/communication-runtime.js.map +1 -0
- package/dist/cjs/collection/consent-repository.js +84 -0
- package/dist/cjs/collection/consent-repository.js.map +1 -0
- package/dist/cjs/collection/copy.js +125 -0
- package/dist/cjs/collection/copy.js.map +1 -0
- package/dist/cjs/collection/delivery-callback.js +151 -0
- package/dist/cjs/collection/delivery-callback.js.map +1 -0
- package/dist/cjs/collection/email-layout.js +252 -0
- package/dist/cjs/collection/email-layout.js.map +1 -0
- package/dist/cjs/collection/engine.js +414 -0
- package/dist/cjs/collection/engine.js.map +1 -0
- package/dist/cjs/collection/format.js +76 -0
- package/dist/cjs/collection/format.js.map +1 -0
- package/dist/cjs/collection/payment-block.js +3 -0
- package/dist/cjs/collection/payment-block.js.map +1 -0
- package/dist/cjs/collection/policy.js +147 -0
- package/dist/cjs/collection/policy.js.map +1 -0
- package/dist/cjs/collection/repository.js +260 -0
- package/dist/cjs/collection/repository.js.map +1 -0
- package/dist/cjs/collection/subject.js +104 -0
- package/dist/cjs/collection/subject.js.map +1 -0
- package/dist/cjs/collection/template-catalog.js +165 -0
- package/dist/cjs/collection/template-catalog.js.map +1 -0
- package/dist/cjs/collection/template.js +78 -0
- package/dist/cjs/collection/template.js.map +1 -0
- package/dist/cjs/communication/adapters/email.js +132 -0
- package/dist/cjs/communication/adapters/email.js.map +1 -0
- package/dist/cjs/communication/adapters/sms.js +127 -0
- package/dist/cjs/communication/adapters/sms.js.map +1 -0
- package/dist/cjs/communication/adapters/whatsapp-language.js +39 -0
- package/dist/cjs/communication/adapters/whatsapp-language.js.map +1 -0
- package/dist/cjs/communication/adapters/whatsapp-templates.js +100 -0
- package/dist/cjs/communication/adapters/whatsapp-templates.js.map +1 -0
- package/dist/cjs/communication/adapters/whatsapp.js +213 -0
- package/dist/cjs/communication/adapters/whatsapp.js.map +1 -0
- package/dist/cjs/communication/audit.js +61 -0
- package/dist/cjs/communication/audit.js.map +1 -0
- package/dist/cjs/communication/capabilities.js +76 -0
- package/dist/cjs/communication/capabilities.js.map +1 -0
- package/dist/cjs/communication/channel.js +53 -0
- package/dist/cjs/communication/channel.js.map +1 -0
- package/dist/cjs/communication/claim.js +228 -0
- package/dist/cjs/communication/claim.js.map +1 -0
- package/dist/cjs/communication/consent.js +43 -0
- package/dist/cjs/communication/consent.js.map +1 -0
- package/dist/cjs/communication/context.js +45 -0
- package/dist/cjs/communication/context.js.map +1 -0
- package/dist/cjs/communication/credentials.js +121 -0
- package/dist/cjs/communication/credentials.js.map +1 -0
- package/dist/cjs/communication/dry-run-scenario.js +161 -0
- package/dist/cjs/communication/dry-run-scenario.js.map +1 -0
- package/dist/cjs/communication/dry-run.js +97 -0
- package/dist/cjs/communication/dry-run.js.map +1 -0
- package/dist/cjs/communication/engine.js +483 -0
- package/dist/cjs/communication/engine.js.map +1 -0
- package/dist/cjs/communication/graph.js +50 -0
- package/dist/cjs/communication/graph.js.map +1 -0
- package/dist/cjs/communication/idempotency.js +26 -0
- package/dist/cjs/communication/idempotency.js.map +1 -0
- package/dist/cjs/communication/identity.js +110 -0
- package/dist/cjs/communication/identity.js.map +1 -0
- package/dist/cjs/communication/index.js +135 -0
- package/dist/cjs/communication/index.js.map +1 -0
- package/dist/cjs/communication/onboarding.js +297 -0
- package/dist/cjs/communication/onboarding.js.map +1 -0
- package/dist/cjs/communication/policy.js +16 -0
- package/dist/cjs/communication/policy.js.map +1 -0
- package/dist/cjs/communication/routing.js +77 -0
- package/dist/cjs/communication/routing.js.map +1 -0
- package/dist/cjs/communication/sender-profile.js +128 -0
- package/dist/cjs/communication/sender-profile.js.map +1 -0
- package/dist/cjs/communication/status.js +86 -0
- package/dist/cjs/communication/status.js.map +1 -0
- package/dist/cjs/communication/stores/onboarding.js +135 -0
- package/dist/cjs/communication/stores/onboarding.js.map +1 -0
- package/dist/cjs/communication/stores/postgres.js +458 -0
- package/dist/cjs/communication/stores/postgres.js.map +1 -0
- package/dist/cjs/communication/stores/routing.js +334 -0
- package/dist/cjs/communication/stores/routing.js.map +1 -0
- package/dist/cjs/communication/stores/secrets.js +126 -0
- package/dist/cjs/communication/stores/secrets.js.map +1 -0
- package/dist/cjs/communication/template-provider.js +22 -0
- package/dist/cjs/communication/template-provider.js.map +1 -0
- package/dist/cjs/communication/template.js +63 -0
- package/dist/cjs/communication/template.js.map +1 -0
- package/dist/cjs/communication/webhook-subscription.js +258 -0
- package/dist/cjs/communication/webhook-subscription.js.map +1 -0
- package/dist/cjs/communication/webhook.js +292 -0
- package/dist/cjs/communication/webhook.js.map +1 -0
- package/dist/cjs/competence/repository.js +309 -0
- package/dist/cjs/competence/repository.js.map +1 -0
- package/dist/cjs/contacts/phone.js +192 -0
- package/dist/cjs/contacts/phone.js.map +1 -0
- package/dist/cjs/db/seed-catalog.js +48 -0
- package/dist/cjs/db/seed-catalog.js.map +1 -0
- package/dist/cjs/db/seed.js +15 -7
- package/dist/cjs/db/seed.js.map +1 -1
- package/dist/cjs/documents/repository.js +244 -0
- package/dist/cjs/documents/repository.js.map +1 -0
- package/dist/cjs/documents/requests.js +136 -0
- package/dist/cjs/documents/requests.js.map +1 -0
- package/dist/cjs/index.js +406 -39
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/legal/documents.js +125 -3
- package/dist/cjs/legal/documents.js.map +1 -1
- package/dist/cjs/legal/types.js +1 -0
- package/dist/cjs/legal/types.js.map +1 -1
- package/dist/cjs/mail/auth-templates.js +29 -0
- package/dist/cjs/mail/auth-templates.js.map +1 -0
- package/dist/cjs/mail/dedup-store.js +12 -51
- package/dist/cjs/mail/dedup-store.js.map +1 -1
- package/dist/cjs/mail/index.js +16 -4
- package/dist/cjs/mail/index.js.map +1 -1
- package/dist/cjs/mail/provider.js +12 -247
- package/dist/cjs/mail/provider.js.map +1 -1
- package/dist/cjs/mail/resend.js +14 -18
- package/dist/cjs/mail/resend.js.map +1 -1
- package/dist/cjs/mail/sender-resolver.js +12 -11
- package/dist/cjs/mail/sender-resolver.js.map +1 -1
- package/dist/cjs/mail/template-renderer.js +11 -16
- package/dist/cjs/mail/template-renderer.js.map +1 -1
- package/dist/cjs/mail/transactional-outbound.js +117 -0
- package/dist/cjs/mail/transactional-outbound.js.map +1 -0
- package/dist/cjs/mail/types.js +8 -35
- package/dist/cjs/mail/types.js.map +1 -1
- package/dist/cjs/portal/provisioning.js +144 -0
- package/dist/cjs/portal/provisioning.js.map +1 -0
- package/dist/cjs/pricing-engine/canonical.js +42 -0
- package/dist/cjs/pricing-engine/canonical.js.map +1 -0
- package/dist/cjs/pricing-engine/errors.js +6 -1
- package/dist/cjs/pricing-engine/errors.js.map +1 -1
- package/dist/cjs/pricing-engine/index.js +12 -1
- package/dist/cjs/pricing-engine/index.js.map +1 -1
- package/dist/cjs/pricing-engine/pipeline.js +200 -26
- package/dist/cjs/pricing-engine/pipeline.js.map +1 -1
- package/dist/cjs/pricing-engine/shadow-adapter.js +79 -0
- package/dist/cjs/pricing-engine/shadow-adapter.js.map +1 -0
- package/dist/cjs/pricing-engine/shadow-diff.js +55 -0
- package/dist/cjs/pricing-engine/shadow-diff.js.map +1 -0
- package/dist/cjs/pricing-engine/shadow-facade.js +85 -0
- package/dist/cjs/pricing-engine/shadow-facade.js.map +1 -0
- package/dist/cjs/pricing-engine/shadow-legacy-types.js +19 -0
- package/dist/cjs/pricing-engine/shadow-legacy-types.js.map +1 -0
- package/dist/cjs/pricing-engine/shadow-metrics.js +34 -0
- package/dist/cjs/pricing-engine/shadow-metrics.js.map +1 -0
- package/dist/cjs/pricing-engine/shadow-normalizer.js +42 -0
- package/dist/cjs/pricing-engine/shadow-normalizer.js.map +1 -0
- package/dist/cjs/rbac/authorize.js +28 -0
- package/dist/cjs/rbac/authorize.js.map +1 -1
- package/dist/cjs/rbac/catalog.js +67 -1
- package/dist/cjs/rbac/catalog.js.map +1 -1
- package/dist/cjs/rbac/workload-provisioning.js +160 -0
- package/dist/cjs/rbac/workload-provisioning.js.map +1 -0
- package/dist/cjs/rbac/workload.js +191 -0
- package/dist/cjs/rbac/workload.js.map +1 -0
- package/dist/cjs/storage/checksum.js +15 -0
- package/dist/cjs/storage/checksum.js.map +1 -0
- package/dist/cjs/storage/key.js +72 -0
- package/dist/cjs/storage/key.js.map +1 -0
- package/dist/cjs/storage/local.js +100 -0
- package/dist/cjs/storage/local.js.map +1 -0
- package/dist/cjs/storage/r2.js +181 -0
- package/dist/cjs/storage/r2.js.map +1 -0
- package/dist/cjs/storage/registry.js +41 -0
- package/dist/cjs/storage/registry.js.map +1 -0
- package/dist/cjs/storage/types.js +50 -0
- package/dist/cjs/storage/types.js.map +1 -0
- package/dist/cjs/subscription-billing/provider/asaas.js +32 -7
- package/dist/cjs/subscription-billing/provider/asaas.js.map +1 -1
- package/dist/cjs/subscription-billing/provider/disabled.js +8 -0
- package/dist/cjs/subscription-billing/provider/disabled.js.map +1 -1
- package/dist/cjs/subscription-billing/provider/registry.js +17 -0
- package/dist/cjs/subscription-billing/provider/registry.js.map +1 -1
- package/dist/cjs/subscription-billing/service.js +57 -8
- package/dist/cjs/subscription-billing/service.js.map +1 -1
- package/dist/cjs/subscription-billing/types.js.map +1 -1
- package/dist/cjs/tenancy/provisioning.js +32 -8
- package/dist/cjs/tenancy/provisioning.js.map +1 -1
- package/dist/cjs/users/repository.js +119 -2
- package/dist/cjs/users/repository.js.map +1 -1
- package/dist/cjs/vault/repository.js +81 -0
- package/dist/cjs/vault/repository.js.map +1 -1
- package/dist/clients/repository.d.ts +42 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +94 -21
- package/dist/clients/repository.js.map +1 -1
- package/dist/collection/branding.d.ts +72 -0
- package/dist/collection/branding.d.ts.map +1 -0
- package/dist/collection/branding.js +136 -0
- package/dist/collection/branding.js.map +1 -0
- package/dist/collection/channel-accounts.d.ts +57 -0
- package/dist/collection/channel-accounts.d.ts.map +1 -0
- package/dist/collection/channel-accounts.js +133 -0
- package/dist/collection/channel-accounts.js.map +1 -0
- package/dist/collection/channel.d.ts +24 -0
- package/dist/collection/channel.d.ts.map +1 -0
- package/dist/collection/channel.js +16 -0
- package/dist/collection/channel.js.map +1 -0
- package/dist/collection/communication-bridge.d.ts +66 -0
- package/dist/collection/communication-bridge.d.ts.map +1 -0
- package/dist/collection/communication-bridge.js +134 -0
- package/dist/collection/communication-bridge.js.map +1 -0
- package/dist/collection/communication-runtime.d.ts +95 -0
- package/dist/collection/communication-runtime.d.ts.map +1 -0
- package/dist/collection/communication-runtime.js +187 -0
- package/dist/collection/communication-runtime.js.map +1 -0
- package/dist/collection/consent-repository.d.ts +32 -0
- package/dist/collection/consent-repository.d.ts.map +1 -0
- package/dist/collection/consent-repository.js +79 -0
- package/dist/collection/consent-repository.js.map +1 -0
- package/dist/collection/copy.d.ts +50 -0
- package/dist/collection/copy.d.ts.map +1 -0
- package/dist/collection/copy.js +122 -0
- package/dist/collection/copy.js.map +1 -0
- package/dist/collection/delivery-callback.d.ts +49 -0
- package/dist/collection/delivery-callback.d.ts.map +1 -0
- package/dist/collection/delivery-callback.js +147 -0
- package/dist/collection/delivery-callback.js.map +1 -0
- package/dist/collection/email-layout.d.ts +45 -0
- package/dist/collection/email-layout.d.ts.map +1 -0
- package/dist/collection/email-layout.js +247 -0
- package/dist/collection/email-layout.js.map +1 -0
- package/dist/collection/engine.d.ts +177 -0
- package/dist/collection/engine.d.ts.map +1 -0
- package/dist/collection/engine.js +407 -0
- package/dist/collection/engine.js.map +1 -0
- package/dist/collection/format.d.ts +32 -0
- package/dist/collection/format.d.ts.map +1 -0
- package/dist/collection/format.js +70 -0
- package/dist/collection/format.js.map +1 -0
- package/dist/collection/payment-block.d.ts +24 -0
- package/dist/collection/payment-block.d.ts.map +1 -0
- package/dist/collection/payment-block.js +2 -0
- package/dist/collection/payment-block.js.map +1 -0
- package/dist/collection/policy.d.ts +53 -0
- package/dist/collection/policy.d.ts.map +1 -0
- package/dist/collection/policy.js +141 -0
- package/dist/collection/policy.js.map +1 -0
- package/dist/collection/repository.d.ts +129 -0
- package/dist/collection/repository.d.ts.map +1 -0
- package/dist/collection/repository.js +246 -0
- package/dist/collection/repository.js.map +1 -0
- package/dist/collection/subject.d.ts +66 -0
- package/dist/collection/subject.d.ts.map +1 -0
- package/dist/collection/subject.js +99 -0
- package/dist/collection/subject.js.map +1 -0
- package/dist/collection/template-catalog.d.ts +16 -0
- package/dist/collection/template-catalog.d.ts.map +1 -0
- package/dist/collection/template-catalog.js +162 -0
- package/dist/collection/template-catalog.js.map +1 -0
- package/dist/collection/template.d.ts +37 -0
- package/dist/collection/template.d.ts.map +1 -0
- package/dist/collection/template.js +73 -0
- package/dist/collection/template.js.map +1 -0
- package/dist/communication/adapters/email.d.ts +28 -0
- package/dist/communication/adapters/email.d.ts.map +1 -0
- package/dist/communication/adapters/email.js +129 -0
- package/dist/communication/adapters/email.js.map +1 -0
- package/dist/communication/adapters/sms.d.ts +95 -0
- package/dist/communication/adapters/sms.d.ts.map +1 -0
- package/dist/communication/adapters/sms.js +121 -0
- package/dist/communication/adapters/sms.js.map +1 -0
- package/dist/communication/adapters/whatsapp-language.d.ts +34 -0
- package/dist/communication/adapters/whatsapp-language.d.ts.map +1 -0
- package/dist/communication/adapters/whatsapp-language.js +36 -0
- package/dist/communication/adapters/whatsapp-language.js.map +1 -0
- package/dist/communication/adapters/whatsapp-templates.d.ts +18 -0
- package/dist/communication/adapters/whatsapp-templates.d.ts.map +1 -0
- package/dist/communication/adapters/whatsapp-templates.js +97 -0
- package/dist/communication/adapters/whatsapp-templates.js.map +1 -0
- package/dist/communication/adapters/whatsapp.d.ts +29 -0
- package/dist/communication/adapters/whatsapp.d.ts.map +1 -0
- package/dist/communication/adapters/whatsapp.js +210 -0
- package/dist/communication/adapters/whatsapp.js.map +1 -0
- package/dist/communication/audit.d.ts +105 -0
- package/dist/communication/audit.d.ts.map +1 -0
- package/dist/communication/audit.js +56 -0
- package/dist/communication/audit.js.map +1 -0
- package/dist/communication/capabilities.d.ts +88 -0
- package/dist/communication/capabilities.d.ts.map +1 -0
- package/dist/communication/capabilities.js +72 -0
- package/dist/communication/capabilities.js.map +1 -0
- package/dist/communication/channel.d.ts +125 -0
- package/dist/communication/channel.d.ts.map +1 -0
- package/dist/communication/channel.js +47 -0
- package/dist/communication/channel.js.map +1 -0
- package/dist/communication/claim.d.ts +368 -0
- package/dist/communication/claim.d.ts.map +1 -0
- package/dist/communication/claim.js +224 -0
- package/dist/communication/claim.js.map +1 -0
- package/dist/communication/consent.d.ts +65 -0
- package/dist/communication/consent.d.ts.map +1 -0
- package/dist/communication/consent.js +40 -0
- package/dist/communication/consent.js.map +1 -0
- package/dist/communication/context.d.ts +48 -0
- package/dist/communication/context.d.ts.map +1 -0
- package/dist/communication/context.js +41 -0
- package/dist/communication/context.js.map +1 -0
- package/dist/communication/credentials.d.ts +74 -0
- package/dist/communication/credentials.d.ts.map +1 -0
- package/dist/communication/credentials.js +115 -0
- package/dist/communication/credentials.js.map +1 -0
- package/dist/communication/dry-run-scenario.d.ts +37 -0
- package/dist/communication/dry-run-scenario.d.ts.map +1 -0
- package/dist/communication/dry-run-scenario.js +158 -0
- package/dist/communication/dry-run-scenario.js.map +1 -0
- package/dist/communication/dry-run.d.ts +40 -0
- package/dist/communication/dry-run.d.ts.map +1 -0
- package/dist/communication/dry-run.js +92 -0
- package/dist/communication/dry-run.js.map +1 -0
- package/dist/communication/engine.d.ts +153 -0
- package/dist/communication/engine.d.ts.map +1 -0
- package/dist/communication/engine.js +480 -0
- package/dist/communication/engine.js.map +1 -0
- package/dist/communication/graph.d.ts +38 -0
- package/dist/communication/graph.d.ts.map +1 -0
- package/dist/communication/graph.js +45 -0
- package/dist/communication/graph.js.map +1 -0
- package/dist/communication/idempotency.d.ts +33 -0
- package/dist/communication/idempotency.d.ts.map +1 -0
- package/dist/communication/idempotency.js +23 -0
- package/dist/communication/idempotency.js.map +1 -0
- package/dist/communication/identity.d.ts +127 -0
- package/dist/communication/identity.d.ts.map +1 -0
- package/dist/communication/identity.js +105 -0
- package/dist/communication/identity.js.map +1 -0
- package/dist/communication/index.d.ts +66 -0
- package/dist/communication/index.d.ts.map +1 -0
- package/dist/communication/index.js +42 -0
- package/dist/communication/index.js.map +1 -0
- package/dist/communication/onboarding.d.ts +223 -0
- package/dist/communication/onboarding.d.ts.map +1 -0
- package/dist/communication/onboarding.js +287 -0
- package/dist/communication/onboarding.js.map +1 -0
- package/dist/communication/policy.d.ts +99 -0
- package/dist/communication/policy.d.ts.map +1 -0
- package/dist/communication/policy.js +13 -0
- package/dist/communication/policy.js.map +1 -0
- package/dist/communication/routing.d.ts +99 -0
- package/dist/communication/routing.d.ts.map +1 -0
- package/dist/communication/routing.js +73 -0
- package/dist/communication/routing.js.map +1 -0
- package/dist/communication/sender-profile.d.ts +100 -0
- package/dist/communication/sender-profile.d.ts.map +1 -0
- package/dist/communication/sender-profile.js +123 -0
- package/dist/communication/sender-profile.js.map +1 -0
- package/dist/communication/status.d.ts +48 -0
- package/dist/communication/status.d.ts.map +1 -0
- package/dist/communication/status.js +79 -0
- package/dist/communication/status.js.map +1 -0
- package/dist/communication/stores/onboarding.d.ts +88 -0
- package/dist/communication/stores/onboarding.d.ts.map +1 -0
- package/dist/communication/stores/onboarding.js +127 -0
- package/dist/communication/stores/onboarding.js.map +1 -0
- package/dist/communication/stores/postgres.d.ts +81 -0
- package/dist/communication/stores/postgres.d.ts.map +1 -0
- package/dist/communication/stores/postgres.js +453 -0
- package/dist/communication/stores/postgres.js.map +1 -0
- package/dist/communication/stores/routing.d.ts +169 -0
- package/dist/communication/stores/routing.d.ts.map +1 -0
- package/dist/communication/stores/routing.js +324 -0
- package/dist/communication/stores/routing.js.map +1 -0
- package/dist/communication/stores/secrets.d.ts +89 -0
- package/dist/communication/stores/secrets.d.ts.map +1 -0
- package/dist/communication/stores/secrets.js +122 -0
- package/dist/communication/stores/secrets.js.map +1 -0
- package/dist/communication/template-provider.d.ts +85 -0
- package/dist/communication/template-provider.d.ts.map +1 -0
- package/dist/communication/template-provider.js +21 -0
- package/dist/communication/template-provider.js.map +1 -0
- package/dist/communication/template.d.ts +87 -0
- package/dist/communication/template.d.ts.map +1 -0
- package/dist/communication/template.js +59 -0
- package/dist/communication/template.js.map +1 -0
- package/dist/communication/webhook-subscription.d.ts +156 -0
- package/dist/communication/webhook-subscription.d.ts.map +1 -0
- package/dist/communication/webhook-subscription.js +252 -0
- package/dist/communication/webhook-subscription.js.map +1 -0
- package/dist/communication/webhook.d.ts +121 -0
- package/dist/communication/webhook.d.ts.map +1 -0
- package/dist/communication/webhook.js +283 -0
- package/dist/communication/webhook.js.map +1 -0
- package/dist/competence/repository.d.ts +147 -0
- package/dist/competence/repository.d.ts.map +1 -0
- package/dist/competence/repository.js +294 -0
- package/dist/competence/repository.js.map +1 -0
- package/dist/contacts/phone.d.ts +70 -0
- package/dist/contacts/phone.d.ts.map +1 -0
- package/dist/contacts/phone.js +186 -0
- package/dist/contacts/phone.js.map +1 -0
- package/dist/db/migrate.js +17 -11
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/seed-catalog.d.ts +18 -0
- package/dist/db/seed-catalog.d.ts.map +1 -0
- package/dist/db/seed-catalog.js +45 -0
- package/dist/db/seed-catalog.js.map +1 -0
- package/dist/db/seed.js +16 -8
- package/dist/db/seed.js.map +1 -1
- package/dist/documents/repository.d.ts +97 -0
- package/dist/documents/repository.d.ts.map +1 -0
- package/dist/documents/repository.js +236 -0
- package/dist/documents/repository.js.map +1 -0
- package/dist/documents/requests.d.ts +73 -0
- package/dist/documents/requests.d.ts.map +1 -0
- package/dist/documents/requests.js +127 -0
- package/dist/documents/requests.js.map +1 -0
- package/dist/index.d.ts +109 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -8
- package/dist/index.js.map +1 -1
- package/dist/legal/documents.d.ts.map +1 -1
- package/dist/legal/documents.js +125 -3
- package/dist/legal/documents.js.map +1 -1
- package/dist/legal/index.d.ts +1 -1
- package/dist/legal/index.d.ts.map +1 -1
- package/dist/legal/types.d.ts +32 -1
- package/dist/legal/types.d.ts.map +1 -1
- package/dist/legal/types.js +1 -0
- package/dist/legal/types.js.map +1 -1
- package/dist/mail/auth-templates.d.ts +15 -0
- package/dist/mail/auth-templates.d.ts.map +1 -0
- package/dist/mail/auth-templates.js +26 -0
- package/dist/mail/auth-templates.js.map +1 -0
- package/dist/mail/dedup-store.d.ts +1 -24
- package/dist/mail/dedup-store.d.ts.map +1 -1
- package/dist/mail/dedup-store.js +9 -48
- package/dist/mail/dedup-store.js.map +1 -1
- package/dist/mail/index.d.ts +2 -1
- package/dist/mail/index.d.ts.map +1 -1
- package/dist/mail/index.js +13 -2
- package/dist/mail/index.js.map +1 -1
- package/dist/mail/provider.d.ts +2 -30
- package/dist/mail/provider.d.ts.map +1 -1
- package/dist/mail/provider.js +10 -246
- package/dist/mail/provider.js.map +1 -1
- package/dist/mail/resend.d.ts +2 -12
- package/dist/mail/resend.d.ts.map +1 -1
- package/dist/mail/resend.js +11 -17
- package/dist/mail/resend.js.map +1 -1
- package/dist/mail/sender-resolver.d.ts +1 -7
- package/dist/mail/sender-resolver.d.ts.map +1 -1
- package/dist/mail/sender-resolver.js +11 -10
- package/dist/mail/sender-resolver.js.map +1 -1
- package/dist/mail/template-renderer.d.ts +1 -9
- package/dist/mail/template-renderer.d.ts.map +1 -1
- package/dist/mail/template-renderer.js +10 -15
- package/dist/mail/template-renderer.js.map +1 -1
- package/dist/mail/transactional-outbound.d.ts +115 -0
- package/dist/mail/transactional-outbound.d.ts.map +1 -0
- package/dist/mail/transactional-outbound.js +113 -0
- package/dist/mail/transactional-outbound.js.map +1 -0
- package/dist/mail/types.d.ts +2 -142
- package/dist/mail/types.d.ts.map +1 -1
- package/dist/mail/types.js +1 -33
- package/dist/mail/types.js.map +1 -1
- package/dist/portal/provisioning.d.ts +58 -0
- package/dist/portal/provisioning.d.ts.map +1 -0
- package/dist/portal/provisioning.js +139 -0
- package/dist/portal/provisioning.js.map +1 -0
- package/dist/pricing-engine/canonical.d.ts +14 -0
- package/dist/pricing-engine/canonical.d.ts.map +1 -0
- package/dist/pricing-engine/canonical.js +39 -0
- package/dist/pricing-engine/canonical.js.map +1 -0
- package/dist/pricing-engine/errors.d.ts.map +1 -1
- package/dist/pricing-engine/errors.js +6 -1
- package/dist/pricing-engine/errors.js.map +1 -1
- package/dist/pricing-engine/index.d.ts +12 -2
- package/dist/pricing-engine/index.d.ts.map +1 -1
- package/dist/pricing-engine/index.js +6 -1
- package/dist/pricing-engine/index.js.map +1 -1
- package/dist/pricing-engine/pipeline.d.ts.map +1 -1
- package/dist/pricing-engine/pipeline.js +202 -28
- package/dist/pricing-engine/pipeline.js.map +1 -1
- package/dist/pricing-engine/shadow-adapter.d.ts +37 -0
- package/dist/pricing-engine/shadow-adapter.d.ts.map +1 -0
- package/dist/pricing-engine/shadow-adapter.js +75 -0
- package/dist/pricing-engine/shadow-adapter.js.map +1 -0
- package/dist/pricing-engine/shadow-diff.d.ts +26 -0
- package/dist/pricing-engine/shadow-diff.d.ts.map +1 -0
- package/dist/pricing-engine/shadow-diff.js +52 -0
- package/dist/pricing-engine/shadow-diff.js.map +1 -0
- package/dist/pricing-engine/shadow-facade.d.ts +42 -0
- package/dist/pricing-engine/shadow-facade.d.ts.map +1 -0
- package/dist/pricing-engine/shadow-facade.js +82 -0
- package/dist/pricing-engine/shadow-facade.js.map +1 -0
- package/dist/pricing-engine/shadow-legacy-types.d.ts +64 -0
- package/dist/pricing-engine/shadow-legacy-types.d.ts.map +1 -0
- package/dist/pricing-engine/shadow-legacy-types.js +18 -0
- package/dist/pricing-engine/shadow-legacy-types.js.map +1 -0
- package/dist/pricing-engine/shadow-metrics.d.ts +33 -0
- package/dist/pricing-engine/shadow-metrics.d.ts.map +1 -0
- package/dist/pricing-engine/shadow-metrics.js +31 -0
- package/dist/pricing-engine/shadow-metrics.js.map +1 -0
- package/dist/pricing-engine/shadow-normalizer.d.ts +17 -0
- package/dist/pricing-engine/shadow-normalizer.d.ts.map +1 -0
- package/dist/pricing-engine/shadow-normalizer.js +39 -0
- package/dist/pricing-engine/shadow-normalizer.js.map +1 -0
- package/dist/pricing-engine/types.d.ts +2 -0
- package/dist/pricing-engine/types.d.ts.map +1 -1
- package/dist/rbac/authorize.d.ts +12 -0
- package/dist/rbac/authorize.d.ts.map +1 -1
- package/dist/rbac/authorize.js +27 -0
- package/dist/rbac/authorize.js.map +1 -1
- package/dist/rbac/catalog.d.ts.map +1 -1
- package/dist/rbac/catalog.js +67 -1
- package/dist/rbac/catalog.js.map +1 -1
- package/dist/rbac/workload-provisioning.d.ts +66 -0
- package/dist/rbac/workload-provisioning.d.ts.map +1 -0
- package/dist/rbac/workload-provisioning.js +153 -0
- package/dist/rbac/workload-provisioning.js.map +1 -0
- package/dist/rbac/workload.d.ts +124 -0
- package/dist/rbac/workload.d.ts.map +1 -0
- package/dist/rbac/workload.js +184 -0
- package/dist/rbac/workload.js.map +1 -0
- package/dist/storage/checksum.d.ts +9 -0
- package/dist/storage/checksum.d.ts.map +1 -0
- package/dist/storage/checksum.js +12 -0
- package/dist/storage/checksum.js.map +1 -0
- package/dist/storage/key.d.ts +37 -0
- package/dist/storage/key.d.ts.map +1 -0
- package/dist/storage/key.js +67 -0
- package/dist/storage/key.js.map +1 -0
- package/dist/storage/local.d.ts +40 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +96 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/storage/r2.d.ts +43 -0
- package/dist/storage/r2.d.ts.map +1 -0
- package/dist/storage/r2.js +177 -0
- package/dist/storage/r2.js.map +1 -0
- package/dist/storage/registry.d.ts +23 -0
- package/dist/storage/registry.d.ts.map +1 -0
- package/dist/storage/registry.js +37 -0
- package/dist/storage/registry.js.map +1 -0
- package/dist/storage/types.d.ts +67 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +45 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/subscription-billing/provider/asaas.d.ts +14 -0
- package/dist/subscription-billing/provider/asaas.d.ts.map +1 -1
- package/dist/subscription-billing/provider/asaas.js +32 -7
- package/dist/subscription-billing/provider/asaas.js.map +1 -1
- package/dist/subscription-billing/provider/disabled.d.ts +9 -0
- package/dist/subscription-billing/provider/disabled.d.ts.map +1 -1
- package/dist/subscription-billing/provider/disabled.js +8 -0
- package/dist/subscription-billing/provider/disabled.js.map +1 -1
- package/dist/subscription-billing/provider/registry.d.ts +10 -0
- package/dist/subscription-billing/provider/registry.d.ts.map +1 -1
- package/dist/subscription-billing/provider/registry.js +17 -0
- package/dist/subscription-billing/provider/registry.js.map +1 -1
- package/dist/subscription-billing/service.d.ts +17 -1
- package/dist/subscription-billing/service.d.ts.map +1 -1
- package/dist/subscription-billing/service.js +57 -8
- package/dist/subscription-billing/service.js.map +1 -1
- package/dist/subscription-billing/types.d.ts +13 -0
- package/dist/subscription-billing/types.d.ts.map +1 -1
- package/dist/subscription-billing/types.js.map +1 -1
- package/dist/tenancy/provisioning.d.ts.map +1 -1
- package/dist/tenancy/provisioning.js +32 -8
- package/dist/tenancy/provisioning.js.map +1 -1
- package/dist/users/repository.d.ts +38 -0
- package/dist/users/repository.d.ts.map +1 -1
- package/dist/users/repository.js +118 -3
- package/dist/users/repository.js.map +1 -1
- package/dist/vault/repository.d.ts +67 -0
- package/dist/vault/repository.d.ts.map +1 -1
- package/dist/vault/repository.js +78 -0
- package/dist/vault/repository.js.map +1 -1
- package/package.json +13 -4
- package/src/db/migrations/0023_user_invite_activation.sql +15 -0
- package/src/db/migrations/0024_set_user_password_function.sql +32 -0
- package/src/db/migrations/0025_revoke_user_session_function.sql +28 -0
- package/src/db/migrations/0026_documents_and_competence.sql +353 -0
- package/src/db/migrations/0027_receivable_client_isolation.sql +58 -0
- package/src/db/migrations/0028_collection_engine.sql +94 -0
- package/src/db/migrations/0029_payment_rail.sql +107 -0
- package/src/db/migrations/0030_provider_account_uniqueness.sql +22 -0
- package/src/db/migrations/0031_provider_account_environment_scope.sql +21 -0
- package/src/db/migrations/0032_settlement_reversal.sql +76 -0
- package/src/db/migrations/0033_receivable_idempotency.sql +28 -0
- package/src/db/migrations/0034_payment_customer_reconcile.sql +30 -0
- package/src/db/migrations/0035_payment_account_environments.sql +61 -0
- package/src/db/migrations/0036_primary_backfill_under_force_rls.sql +41 -0
- package/src/db/migrations/0037_receivable_generation_source.sql +29 -0
- package/src/db/migrations/0038_notification_channels.sql +175 -0
- package/src/db/migrations/0039_communication_dispatch_claim.sql +193 -0
- package/src/db/migrations/0040_communication_unknown_outcome.sql +99 -0
- package/src/db/migrations/0041_channel_binding_routing.sql +146 -0
- package/src/db/migrations/0042_channel_route_read_isolation.sql +165 -0
- package/src/db/migrations/0043_workload_identity.sql +105 -0
- package/src/db/migrations/0044_channel_onboarding_session.sql +96 -0
- package/dist/cjs/mail/resend-client.js +0 -103
- package/dist/cjs/mail/resend-client.js.map +0 -1
- package/dist/mail/resend-client.d.ts +0 -16
- package/dist/mail/resend-client.d.ts.map +0 -1
- package/dist/mail/resend-client.js +0 -100
- package/dist/mail/resend-client.js.map +0 -1
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Persistência do vínculo de canal e do índice de roteamento
|
|
4
|
+
* (migrações 0041 e 0042).
|
|
5
|
+
*
|
|
6
|
+
* Duas leituras, com fronteiras deliberadamente diferentes:
|
|
7
|
+
*
|
|
8
|
+
* - `createPostgresChannelBindingStore` responde "qual a conta DESTE tenant
|
|
9
|
+
* neste canal", dentro do contexto do tenant, sob RLS.
|
|
10
|
+
* - `createPostgresChannelRouteStore` responde "de quem é esta conta do
|
|
11
|
+
* provider", FORA de contexto de tenant, porque no momento em que o webhook
|
|
12
|
+
* chega ainda não se sabe qual é o tenant.
|
|
13
|
+
*
|
|
14
|
+
* A segunda é a única leitura do motor que roda sem `app.current_tenant` — e
|
|
15
|
+
* ela não lê a tabela. Passa por `channel_route_resolve`, uma função de sistema
|
|
16
|
+
* que exige a chave exata e devolve no máximo uma linha. A tabela em si voltou
|
|
17
|
+
* a ser fechada por tenant na 0042: sem GUC, `SELECT * FROM channel_route`
|
|
18
|
+
* devolve zero linhas.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.CredentialRefNotAcceptableError = exports.ChannelRouteConflictError = void 0;
|
|
22
|
+
exports.createPostgresChannelRouteStore = createPostgresChannelRouteStore;
|
|
23
|
+
exports.completeRoute = completeRoute;
|
|
24
|
+
exports.createPostgresChannelBindingStore = createPostgresChannelBindingStore;
|
|
25
|
+
exports.registerChannelBinding = registerChannelBinding;
|
|
26
|
+
exports.claimChannelAccount = claimChannelAccount;
|
|
27
|
+
const credentials_js_1 = require("../credentials.js");
|
|
28
|
+
/**
|
|
29
|
+
* Índice de roteamento — primeiro tempo da resolução.
|
|
30
|
+
*
|
|
31
|
+
* Devolve o MÍNIMO: quem é o dono. Produto e marca ficam de fora porque vivem
|
|
32
|
+
* em `channel_binding`, que é fechada por RLS e portanto ilegível neste momento
|
|
33
|
+
* — ainda não há tenant na sessão. Denormalizá-los aqui resolveria a consulta e
|
|
34
|
+
* colocaria "que produto este escritório assina" atrás da mesma função que
|
|
35
|
+
* responde sem contexto de tenant, o que é informação comercial em lugar
|
|
36
|
+
* errado.
|
|
37
|
+
*
|
|
38
|
+
* O segundo tempo é `completeRoute`, já dentro de `withContext`.
|
|
39
|
+
*/
|
|
40
|
+
function createPostgresChannelRouteStore(tx) {
|
|
41
|
+
return {
|
|
42
|
+
async findByProviderAccount(provider, providerAccountRef) {
|
|
43
|
+
// `channel_route_resolve` (migração 0042), e não um `SELECT` na tabela.
|
|
44
|
+
//
|
|
45
|
+
// A 0041 abria a política de leitura quando não havia tenant na sessão,
|
|
46
|
+
// e essa abertura era o que fazia este `SELECT` funcionar. O preço era
|
|
47
|
+
// que QUALQUER consulta sem contexto — um script, um job, um caminho que
|
|
48
|
+
// esqueceu de abrir `withContext` — enxergava o mapa inteiro de
|
|
49
|
+
// (conta do provider → tenant) e podia listá-lo.
|
|
50
|
+
//
|
|
51
|
+
// A função de sistema entrega a mesma resposta sem o mesmo preço: exige a
|
|
52
|
+
// chave exata, devolve no máximo uma linha e não tem forma de ser
|
|
53
|
+
// chamada "sem argumento". A política da tabela voltou a ser fechada, e
|
|
54
|
+
// ninguém lê `channel_route` fora do próprio tenant.
|
|
55
|
+
const rows = await tx `
|
|
56
|
+
SELECT provider, provider_account_ref, provider_parent_ref, tenant_id, binding_id
|
|
57
|
+
FROM channel_route_resolve(${provider}, ${providerAccountRef})
|
|
58
|
+
`;
|
|
59
|
+
const row = rows[0];
|
|
60
|
+
if (!row)
|
|
61
|
+
return null;
|
|
62
|
+
return {
|
|
63
|
+
provider,
|
|
64
|
+
providerAccountRef: row.provider_account_ref,
|
|
65
|
+
...(row.provider_parent_ref ? { providerParentRef: row.provider_parent_ref } : {}),
|
|
66
|
+
tenantId: row.tenant_id,
|
|
67
|
+
// Preenchidos por `completeRoute`, dentro do contexto do tenant.
|
|
68
|
+
product: '',
|
|
69
|
+
brand: '',
|
|
70
|
+
bindingId: row.binding_id,
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* O único estado de vínculo que autoriza tráfego.
|
|
77
|
+
*
|
|
78
|
+
* Lista de PERMISSÃO, e não de bloqueio. Uma lista de bloqueio
|
|
79
|
+
* (`status !== 'paused'`) autoriza por omissão: o dia em que a coluna ganhar
|
|
80
|
+
* `suspended`, `blocked` ou `migrating`, o estado novo nasce liberado e ninguém
|
|
81
|
+
* repara. Aqui um estado que ninguém escreveu aqui não passa, inclusive um
|
|
82
|
+
* valor que a aplicação não reconhece.
|
|
83
|
+
*/
|
|
84
|
+
const ROUTABLE_STATUSES = new Set(['active']);
|
|
85
|
+
/**
|
|
86
|
+
* Completa a rota com produto e marca, JÁ dentro do contexto do tenant.
|
|
87
|
+
*
|
|
88
|
+
* Separado de propósito: a primeira consulta responde "de quem é", a segunda
|
|
89
|
+
* responde "o que é" — e a segunda roda sob a RLS de `channel_binding`, que é
|
|
90
|
+
* fechada.
|
|
91
|
+
*
|
|
92
|
+
* Três gates, e o terceiro estava faltando na primeira entrega. A revogação era
|
|
93
|
+
* conferida (`revoked_at IS NULL`) e o STATUS não — de modo que um vínculo
|
|
94
|
+
* `paused`, `error`, `pending_validation` ou `not_configured`, que ninguém
|
|
95
|
+
* revogou, continuava roteando. É a assimetria clássica: o caminho de saída
|
|
96
|
+
* consultava o status (`identity.ts` só envia por conta `active`) e o de
|
|
97
|
+
* entrada não, e uma conta pausada por suspeita de abuso seguia recebendo.
|
|
98
|
+
*/
|
|
99
|
+
async function completeRoute(tx, route) {
|
|
100
|
+
const rows = await tx `
|
|
101
|
+
SELECT product, brand, status
|
|
102
|
+
FROM channel_binding
|
|
103
|
+
WHERE id = ${route.bindingId}
|
|
104
|
+
AND tenant_id = ${route.tenantId}
|
|
105
|
+
AND revoked_at IS NULL
|
|
106
|
+
LIMIT 1
|
|
107
|
+
`;
|
|
108
|
+
const row = rows[0];
|
|
109
|
+
if (!row)
|
|
110
|
+
return null;
|
|
111
|
+
if (!ROUTABLE_STATUSES.has(row.status))
|
|
112
|
+
return null;
|
|
113
|
+
return { ...route, product: row.product, brand: row.brand };
|
|
114
|
+
}
|
|
115
|
+
const STATUSES = new Set([
|
|
116
|
+
'not_configured',
|
|
117
|
+
'pending_validation',
|
|
118
|
+
'active',
|
|
119
|
+
'paused',
|
|
120
|
+
'error',
|
|
121
|
+
]);
|
|
122
|
+
/**
|
|
123
|
+
* Contas de canal a partir de `channel_binding`.
|
|
124
|
+
*
|
|
125
|
+
* Substitui, para os canais de telefone, a leitura de `tenant.settings.channels`
|
|
126
|
+
* — que continua existindo e continua servindo o e-mail e a configuração
|
|
127
|
+
* herdada. Não há fallback de um para o outro dentro desta função: quem compõe
|
|
128
|
+
* o runtime decide a ordem, e a decisão fica visível na composição em vez de
|
|
129
|
+
* escondida num `??`.
|
|
130
|
+
*/
|
|
131
|
+
function createPostgresChannelBindingStore(tx) {
|
|
132
|
+
return {
|
|
133
|
+
async find(ctx, channel) {
|
|
134
|
+
const rows = await tx `
|
|
135
|
+
SELECT b.id, b.product, b.brand, b.channel, b.sender_id, b.display_name,
|
|
136
|
+
b.credential_ref, b.status,
|
|
137
|
+
r.provider_account_ref, r.provider_parent_ref
|
|
138
|
+
FROM channel_binding b
|
|
139
|
+
LEFT JOIN channel_route r
|
|
140
|
+
ON r.tenant_id = b.tenant_id AND r.binding_id = b.id
|
|
141
|
+
WHERE b.tenant_id = ${ctx.tenantId}
|
|
142
|
+
AND b.product = ${ctx.product}
|
|
143
|
+
AND b.brand = ${ctx.brand}
|
|
144
|
+
AND b.channel = ${channel}
|
|
145
|
+
AND b.revoked_at IS NULL
|
|
146
|
+
LIMIT 1
|
|
147
|
+
`;
|
|
148
|
+
const row = rows[0];
|
|
149
|
+
if (!row)
|
|
150
|
+
return null;
|
|
151
|
+
const meta = {};
|
|
152
|
+
if (row.provider_account_ref)
|
|
153
|
+
meta.phoneNumberId = row.provider_account_ref;
|
|
154
|
+
if (row.provider_parent_ref)
|
|
155
|
+
meta.wabaId = row.provider_parent_ref;
|
|
156
|
+
return {
|
|
157
|
+
channel,
|
|
158
|
+
tenantId: ctx.tenantId,
|
|
159
|
+
product: row.product,
|
|
160
|
+
brand: row.brand,
|
|
161
|
+
senderId: row.sender_id,
|
|
162
|
+
...(row.display_name ? { displayName: row.display_name } : {}),
|
|
163
|
+
credentialRef: row.credential_ref,
|
|
164
|
+
// Estado desconhecido nunca vira `active`: configuração que ninguém
|
|
165
|
+
// reconhece não autoriza envio.
|
|
166
|
+
status: STATUSES.has(row.status)
|
|
167
|
+
? row.status
|
|
168
|
+
: 'not_configured',
|
|
169
|
+
...(Object.keys(meta).length > 0 ? { meta } : {}),
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Registra ou atualiza um vínculo e sua rota. **Roda dentro do contexto do
|
|
176
|
+
* tenant** — as duas políticas de escrita exigem isso.
|
|
177
|
+
*
|
|
178
|
+
* O `INSERT` da rota falha por violação de chave primária quando outro tenant já
|
|
179
|
+
* reivindicou a mesma conta do provider. Isso é o comportamento desejado e é a
|
|
180
|
+
* razão de a chave ser global: o erro vem do banco, não de um `SELECT` prévio
|
|
181
|
+
* que a RLS teria feito voltar vazio.
|
|
182
|
+
*
|
|
183
|
+
* ── O guard de credencial ───────────────────────────────────────────────────
|
|
184
|
+
*
|
|
185
|
+
* `isAcceptableForNewBinding` existia e **não era chamado por ninguém**. Uma
|
|
186
|
+
* regra que só um teste unitário exercita não é enforcement: é documentação com
|
|
187
|
+
* sintaxe de TypeScript. O caminho real de criação aceitava, sem reclamar,
|
|
188
|
+
* `credentialRef: 'WHATSAPP_ACCESS_TOKEN'` — o token global que a fase inteira
|
|
189
|
+
* existe para eliminar.
|
|
190
|
+
*
|
|
191
|
+
* A checagem vem ANTES de qualquer escrita, e cobre criação e atualização pelo
|
|
192
|
+
* mesmo ponto porque este `INSERT ... ON CONFLICT DO UPDATE` É os dois. O banco
|
|
193
|
+
* repete a regra em `channel_binding_phone_credential_ref_chk` (migração 0042),
|
|
194
|
+
* para o caso de alguém alcançar a tabela por outro caminho: um `UPDATE` cru,
|
|
195
|
+
* uma importação, um script de migração de dados.
|
|
196
|
+
*/
|
|
197
|
+
async function registerChannelBinding(tx, input) {
|
|
198
|
+
if (!(0, credentials_js_1.isAcceptableForNewBinding)(input.channel, input.credentialRef)) {
|
|
199
|
+
throw new CredentialRefNotAcceptableError(input.channel, input.credentialRef);
|
|
200
|
+
}
|
|
201
|
+
await tx `
|
|
202
|
+
INSERT INTO channel_binding
|
|
203
|
+
(id, tenant_id, product, brand, channel, provider, sender_id, display_name,
|
|
204
|
+
credential_ref, status)
|
|
205
|
+
VALUES
|
|
206
|
+
(${input.id}, ${input.tenantId}, ${input.product}, ${input.brand}, ${input.channel},
|
|
207
|
+
${input.provider}, ${input.senderId}, ${input.displayName ?? null},
|
|
208
|
+
${input.credentialRef}, ${input.status ?? 'not_configured'})
|
|
209
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
210
|
+
sender_id = EXCLUDED.sender_id,
|
|
211
|
+
display_name = EXCLUDED.display_name,
|
|
212
|
+
credential_ref = EXCLUDED.credential_ref,
|
|
213
|
+
status = EXCLUDED.status,
|
|
214
|
+
updated_at = now()
|
|
215
|
+
`;
|
|
216
|
+
if (!input.providerAccountRef)
|
|
217
|
+
return;
|
|
218
|
+
const claimed = await tx `
|
|
219
|
+
INSERT INTO channel_route
|
|
220
|
+
(provider, provider_account_ref, provider_parent_ref, tenant_id, binding_id)
|
|
221
|
+
VALUES
|
|
222
|
+
(${input.provider}, ${input.providerAccountRef}, ${input.providerParentRef ?? null},
|
|
223
|
+
${input.tenantId}, ${input.id})
|
|
224
|
+
ON CONFLICT (provider, provider_account_ref) DO UPDATE SET
|
|
225
|
+
provider_parent_ref = EXCLUDED.provider_parent_ref,
|
|
226
|
+
updated_at = now()
|
|
227
|
+
WHERE channel_route.tenant_id = EXCLUDED.tenant_id
|
|
228
|
+
AND channel_route.binding_id = EXCLUDED.binding_id
|
|
229
|
+
RETURNING provider_account_ref
|
|
230
|
+
`;
|
|
231
|
+
// Zero linhas com `ON CONFLICT DO UPDATE` significa que o conflito existe e o
|
|
232
|
+
// `WHERE` recusou — ou seja, a conta já pertence a OUTRO vínculo. Deixar
|
|
233
|
+
// passar em silêncio é o pior desfecho possível: o registro pareceria ter
|
|
234
|
+
// funcionado e os webhooks continuariam indo para o dono anterior.
|
|
235
|
+
if (claimed.count === 0) {
|
|
236
|
+
throw new ChannelRouteConflictError(input.provider, input.providerAccountRef);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* A conta do provider já pertence a outro vínculo.
|
|
241
|
+
*
|
|
242
|
+
* Erro de negócio, não de infraestrutura: dois escritórios não podem reivindicar
|
|
243
|
+
* o mesmo número. A mensagem não carrega o tenant dono — quem está tentando
|
|
244
|
+
* registrar não tem por que descobrir de quem é.
|
|
245
|
+
*/
|
|
246
|
+
class ChannelRouteConflictError extends Error {
|
|
247
|
+
code = 'channel_route_conflict';
|
|
248
|
+
constructor(provider, providerAccountRef) {
|
|
249
|
+
super(`conta ${provider}/${providerAccountRef} já vinculada a outro registro`);
|
|
250
|
+
this.name = 'ChannelRouteConflictError';
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.ChannelRouteConflictError = ChannelRouteConflictError;
|
|
254
|
+
/**
|
|
255
|
+
* A referência de credencial não é aceitável para este canal.
|
|
256
|
+
*
|
|
257
|
+
* O canal de telefone exige `vault://` — uma referência ao cofre do TENANT.
|
|
258
|
+
* Aceitar um nome de variável de ambiente significaria, na prática, que dois
|
|
259
|
+
* escritórios compartilham o mesmo token de WhatsApp: o bloqueio que um tomar
|
|
260
|
+
* cai sobre o outro, e a conversa de um aparece na conta do outro.
|
|
261
|
+
*
|
|
262
|
+
* A mensagem carrega o canal e **não** carrega a referência recusada. Quem
|
|
263
|
+
* cadastrou já sabe o que digitou; a mensagem viaja para log e para tela de
|
|
264
|
+
* erro, e uma referência colada ali é meio caminho para o valor aparecer junto
|
|
265
|
+
* na próxima vez que alguém "melhorar o diagnóstico".
|
|
266
|
+
*/
|
|
267
|
+
class CredentialRefNotAcceptableError extends Error {
|
|
268
|
+
code = 'credential_ref_not_acceptable';
|
|
269
|
+
channel;
|
|
270
|
+
constructor(channel, _ref) {
|
|
271
|
+
super(`canal ${channel} exige referência de cofre (vault://) — referência recusada`);
|
|
272
|
+
this.name = 'CredentialRefNotAcceptableError';
|
|
273
|
+
this.channel = channel;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
exports.CredentialRefNotAcceptableError = CredentialRefNotAcceptableError;
|
|
277
|
+
/**
|
|
278
|
+
* Registra a conta de canal do contexto — criando o vínculo ou **substituindo o
|
|
279
|
+
* que já existe**.
|
|
280
|
+
*
|
|
281
|
+
* ## Por que `registerChannelBinding` sozinho não serve ao onboarding
|
|
282
|
+
*
|
|
283
|
+
* `channel_binding_context_uq` (0041) garante **um** vínculo vivo por
|
|
284
|
+
* (tenant, produto, marca, canal) — é o que faz `resolveIdentity` nunca ter de
|
|
285
|
+
* escolher entre dois. `registerChannelBinding` resolve conflito por `id`, e o
|
|
286
|
+
* `id` de um onboarding novo é novo: reconectar o WhatsApp de um escritório que
|
|
287
|
+
* já tinha um caía direto na violação do índice de contexto, como erro 500.
|
|
288
|
+
*
|
|
289
|
+
* Isso não é caso de laboratório. É o caminho de: trocar de número, refazer o
|
|
290
|
+
* signup depois de revogar o acesso, migrar a WABA de portfólio. O primeiro
|
|
291
|
+
* onboarding funcionava e o segundo derrubava a rota.
|
|
292
|
+
*
|
|
293
|
+
* ## As rotas órfãs, que são o risco silencioso
|
|
294
|
+
*
|
|
295
|
+
* Trocar o número deixaria a rota do número ANTIGO apontando para este mesmo
|
|
296
|
+
* vínculo — e o webhook do número que o escritório não usa mais continuaria
|
|
297
|
+
* sendo aceito e aplicado na trilha dele. Pior: aquele número fica preso a este
|
|
298
|
+
* tenant pela chave global de `channel_route`, e o escritório que o receber
|
|
299
|
+
* depois não consegue reivindicá-lo.
|
|
300
|
+
*
|
|
301
|
+
* Por isso a limpeza é parte da mesma operação, e não um passo que quem chama
|
|
302
|
+
* precisa lembrar de fazer.
|
|
303
|
+
*/
|
|
304
|
+
async function claimChannelAccount(tx, input) {
|
|
305
|
+
const existing = await tx `
|
|
306
|
+
SELECT id FROM channel_binding
|
|
307
|
+
WHERE tenant_id = ${input.tenantId}
|
|
308
|
+
AND product = ${input.product}
|
|
309
|
+
AND brand = ${input.brand}
|
|
310
|
+
AND channel = ${input.channel}
|
|
311
|
+
AND revoked_at IS NULL
|
|
312
|
+
LIMIT 1
|
|
313
|
+
`;
|
|
314
|
+
const bindingId = existing[0]?.id ?? input.id;
|
|
315
|
+
await registerChannelBinding(tx, { ...input, id: bindingId });
|
|
316
|
+
// Só depois de a rota nova estar reivindicada. Apagar antes deixaria o
|
|
317
|
+
// vínculo sem rota nenhuma se o `INSERT` seguinte falhasse por conflito — e o
|
|
318
|
+
// canal do escritório pararia de receber callbacks por causa da tentativa
|
|
319
|
+
// frustrada de outro.
|
|
320
|
+
const released = input.providerAccountRef
|
|
321
|
+
? await tx `
|
|
322
|
+
DELETE FROM channel_route
|
|
323
|
+
WHERE tenant_id = ${input.tenantId}
|
|
324
|
+
AND binding_id = ${bindingId}
|
|
325
|
+
AND provider_account_ref <> ${input.providerAccountRef}
|
|
326
|
+
`
|
|
327
|
+
: { count: 0 };
|
|
328
|
+
return {
|
|
329
|
+
bindingId,
|
|
330
|
+
reused: Boolean(existing[0]),
|
|
331
|
+
releasedRoutes: released.count,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=routing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../../src/communication/stores/routing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `TenantSecretStore` sobre o Vault Engine — agora atrás de autorização real.
|
|
4
|
+
*
|
|
5
|
+
* `credentials.ts` já declarava a interface e já dizia por que o valor teria
|
|
6
|
+
* de vir do cofre (migração 0012), mas nenhum arquivo do repositório a
|
|
7
|
+
* implementava: `createChannelCredentialResolver` só era chamado em teste, e
|
|
8
|
+
* os três call sites de produção (`collection-cron.ts`, `routes/collections.ts`)
|
|
9
|
+
* seguiam presos a `environmentCredentialResolver()`. Uma referência
|
|
10
|
+
* `vault://...` resolvia para `undefined` em produção — não por bug, por
|
|
11
|
+
* ausência: o fio entre o cofre e o motor nunca foi ligado.
|
|
12
|
+
*
|
|
13
|
+
* Este módulo é esse fio. Não é um segundo cofre — reaproveita
|
|
14
|
+
* `vault/repository.ts` inteiro (RLS FORCE, AAD por tenant, envelope
|
|
15
|
+
* AES-256-GCM) e acrescenta só o que o motor precisava e o Vault não tinha:
|
|
16
|
+
* ler por NOME em vez de `id` (`revealSecretByName`).
|
|
17
|
+
*
|
|
18
|
+
* **O que mudou no lote C1A.1.** A primeira versão aceitava um
|
|
19
|
+
* `SecretAccessGrant` montado pelo CHAMADOR: `principal` e `reason` eram
|
|
20
|
+
* strings, e qualquer módulo interno podia declará-las e pedir decifração.
|
|
21
|
+
* Isso registrava quem disse ser — não provava quem era. Agora o store exige
|
|
22
|
+
* uma `WorkloadIdentity` autenticada (`rbac/workload.ts`), e cada `reveal()`
|
|
23
|
+
* consulta o banco, DENTRO da mesma transação, para saber se aquele principal
|
|
24
|
+
* tem `vault.credential.decrypt` NAQUELE tenant, para AQUELE propósito e sobre
|
|
25
|
+
* AQUELE nome de credencial. O grant deixou de ser declaração e virou linha em
|
|
26
|
+
* tabela que o papel da aplicação não consegue escrever.
|
|
27
|
+
*
|
|
28
|
+
* O `SecretAccessGrant` permanece — como REGISTRO DE AUDITORIA derivado da
|
|
29
|
+
* decisão, não como entrada. É o que vai para o `audit_log`.
|
|
30
|
+
*/
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.VAULT_DECRYPT_PERMISSION = void 0;
|
|
33
|
+
exports.createPostgresTenantSecretStore = createPostgresTenantSecretStore;
|
|
34
|
+
const audit_js_1 = require("../../audit/audit.js");
|
|
35
|
+
const context_js_1 = require("../../db/context.js");
|
|
36
|
+
const workload_js_1 = require("../../rbac/workload.js");
|
|
37
|
+
const repository_js_1 = require("../../vault/repository.js");
|
|
38
|
+
/** A permissão do catálogo RBAC exigida para decifrar. Uma só, específica. */
|
|
39
|
+
exports.VAULT_DECRYPT_PERMISSION = 'vault.credential.decrypt';
|
|
40
|
+
const ACTOR_TYPE = 'automation';
|
|
41
|
+
/**
|
|
42
|
+
* `TenantSecretStore` sobre o Vault Engine.
|
|
43
|
+
*
|
|
44
|
+
* `reveal(tenantId, name)` recebe `tenantId` POR CHAMADA — o store é
|
|
45
|
+
* construído uma vez, no processo, e serve qualquer tenant que o motor
|
|
46
|
+
* resolver depois. É o mesmo desenho de `createChannelCredentialResolver`:
|
|
47
|
+
* quem sabe o tenant é o CHAMADOR, nunca o store. Mas saber o tenant não
|
|
48
|
+
* autoriza: cada chamada é decidida contra os grants DAQUELE tenant.
|
|
49
|
+
*
|
|
50
|
+
* Deny-by-default em toda borda:
|
|
51
|
+
* - identidade não emitida por `authenticateWorkload` → lança na CONSTRUÇÃO
|
|
52
|
+
* - `tenantId`/`name` vazios → nega sem tocar o banco
|
|
53
|
+
* - sessão expirada → nega, audita `denied`
|
|
54
|
+
* - principal revogado/desabilitado → nega, audita `denied`
|
|
55
|
+
* - sem grant casando tenant+permissão+propósito+recurso → nega, audita `denied`
|
|
56
|
+
* - nome inexistente/revogado/de outro tenant → nega (RLS filtra a linha)
|
|
57
|
+
* - vencida (`expires_at`) → nega, NUNCA decifra
|
|
58
|
+
* - erro de infraestrutura → propaga (não é "ausência"; é falha)
|
|
59
|
+
*
|
|
60
|
+
* Toda chamada que chega ao banco grava uma linha em `audit_log` —
|
|
61
|
+
* sucesso, ausência ou negação. O reveal nunca é silencioso.
|
|
62
|
+
*/
|
|
63
|
+
function createPostgresTenantSecretStore(db, keyring, identity, options) {
|
|
64
|
+
// Identidade forjada não passa da construção. Um `ForbiddenError` no boot é
|
|
65
|
+
// muito melhor que um `undefined` na primeira tentativa de envio.
|
|
66
|
+
(0, workload_js_1.assertMintedWorkloadIdentity)(identity);
|
|
67
|
+
const purpose = options?.purpose;
|
|
68
|
+
const correlationId = options?.correlationId ?? null;
|
|
69
|
+
const auditBase = (grantId, denyReason) => ({
|
|
70
|
+
purpose,
|
|
71
|
+
principal: identity.principalKey,
|
|
72
|
+
principalId: identity.principalId,
|
|
73
|
+
permission: exports.VAULT_DECRYPT_PERMISSION,
|
|
74
|
+
grantId,
|
|
75
|
+
correlationId,
|
|
76
|
+
...(denyReason ? { denyReason } : {}),
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
async reveal(tenantId, name) {
|
|
80
|
+
const trimmedTenant = tenantId?.trim() ?? '';
|
|
81
|
+
const trimmedName = name?.trim() ?? '';
|
|
82
|
+
// Contexto insuficiente: nem abre transação. Não há tenant para auditar
|
|
83
|
+
// contra, e um GUC vazio não é "nenhum tenant" — é erro de outra camada.
|
|
84
|
+
if (!trimmedTenant || !trimmedName)
|
|
85
|
+
return undefined;
|
|
86
|
+
return (0, context_js_1.withContext)(db, { tenantId: trimmedTenant }, async (tx) => {
|
|
87
|
+
const audit = async (result, grantId, denyReason, resourceId) => {
|
|
88
|
+
await (0, audit_js_1.appendAudit)(tx, {
|
|
89
|
+
actorType: ACTOR_TYPE,
|
|
90
|
+
// `audit_log.actor_id` tem FK para `"user"(id)` — um principal de
|
|
91
|
+
// workload não é usuário e não cabe ali. A identidade vai em
|
|
92
|
+
// `metadata.principalId`, que é um uuid, não um segredo.
|
|
93
|
+
actorId: null,
|
|
94
|
+
action: 'vault.reveal',
|
|
95
|
+
resourceType: 'vault_credential',
|
|
96
|
+
...(resourceId ? { resourceId } : {}),
|
|
97
|
+
result,
|
|
98
|
+
metadata: { name: trimmedName, ...auditBase(grantId, denyReason) },
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const decision = await (0, workload_js_1.authorizeWorkload)(tx, identity, {
|
|
102
|
+
tenantId: trimmedTenant,
|
|
103
|
+
permission: exports.VAULT_DECRYPT_PERMISSION,
|
|
104
|
+
purpose,
|
|
105
|
+
resource: trimmedName,
|
|
106
|
+
});
|
|
107
|
+
if (!decision.allowed) {
|
|
108
|
+
await audit('denied', null, decision.denyReason);
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const found = await (0, repository_js_1.revealSecretByName)(tx, keyring, trimmedTenant, trimmedName);
|
|
112
|
+
if (!found) {
|
|
113
|
+
await audit('failure', decision.grantId, 'not_found_or_revoked');
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
if (found.status === 'expired') {
|
|
117
|
+
await audit('failure', decision.grantId, 'expired', found.meta.id);
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
await audit('success', decision.grantId, undefined, found.meta.id);
|
|
121
|
+
return found.secret;
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../../src/communication/stores/secrets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Submissão de template de mensagem — contrato do DOMÍNIO.
|
|
4
|
+
*
|
|
5
|
+
* ## Por que existe separado do adapter
|
|
6
|
+
*
|
|
7
|
+
* Canais que exigem template aprovado não são exclusividade do WhatsApp: RCS e
|
|
8
|
+
* boa parte dos provedores de SMS transacional pedem o mesmo. O que o domínio
|
|
9
|
+
* precisa expressar é a INTENÇÃO — "submeter este texto, com estas variáveis,
|
|
10
|
+
* nesta categoria, para aprovação" — e não `POST /{waba-id}/message_templates`.
|
|
11
|
+
*
|
|
12
|
+
* Nada aqui menciona Meta, WABA ou Graph API. Trocar de provider é escrever
|
|
13
|
+
* outro adapter; nenhuma linha de catálogo, régua ou motor muda.
|
|
14
|
+
*
|
|
15
|
+
* ## O que o domínio NÃO decide
|
|
16
|
+
*
|
|
17
|
+
* O texto. Ele vem do consumidor, porque a forma como um escritório fala com o
|
|
18
|
+
* cliente é dele — o motor guarda e resolve templates, e não contém nenhum
|
|
19
|
+
* (adendo §14).
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
//# sourceMappingURL=template-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-provider.js","sourceRoot":"","sources":["../../../src/communication/template-provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Modelo de template do motor compartilhado.
|
|
4
|
+
*
|
|
5
|
+
* O motor guarda e resolve templates. Ele **não contém nenhum**: nenhuma string
|
|
6
|
+
* de cobrança da SC, nenhum texto de assinatura da Dental. O catálogo é dado do
|
|
7
|
+
* consumidor, e é assim que "motor compartilhado" não vira "monolito central
|
|
8
|
+
* cheio de regra de negócio alheia" (adendo §14).
|
|
9
|
+
*
|
|
10
|
+
* O que o motor sabe é o que todo canal precisa que alguém saiba: qual template
|
|
11
|
+
* vale para este contexto, nesta versão, neste idioma, e se ele está aprovado.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.resolveTemplate = resolveTemplate;
|
|
15
|
+
exports.orderVariables = orderVariables;
|
|
16
|
+
/**
|
|
17
|
+
* Especificidade do escopo — maior vence.
|
|
18
|
+
*
|
|
19
|
+
* Tenant+marca (3) > tenant (2) > marca do produto (1) > produto (0). Um
|
|
20
|
+
* escritório que personalizou o próprio texto não pode ser sobrescrito pelo
|
|
21
|
+
* padrão do produto só porque o padrão foi atualizado depois.
|
|
22
|
+
*/
|
|
23
|
+
function specificity(t) {
|
|
24
|
+
return (t.tenantId ? 2 : 0) + (t.brand ? 1 : 0);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolve o template mais específico e aprovado.
|
|
28
|
+
*
|
|
29
|
+
* Um candidato de escopo mais específico porém NÃO aprovado não silencia os
|
|
30
|
+
* menos específicos — cair para o padrão do produto é melhor que não enviar. Mas
|
|
31
|
+
* também não é escolhido: enviar um rascunho seria pior que os dois.
|
|
32
|
+
*/
|
|
33
|
+
async function resolveTemplate(store, ctx, channel, eventType, locale) {
|
|
34
|
+
const all = await store.candidates(ctx, channel, eventType, locale);
|
|
35
|
+
if (all.length === 0) {
|
|
36
|
+
return { ok: false, reason: 'not_found', detail: `sem template para ${eventType}/${channel}` };
|
|
37
|
+
}
|
|
38
|
+
const approved = all.filter((t) => t.status === 'approved');
|
|
39
|
+
if (approved.length === 0) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
reason: 'not_approved',
|
|
43
|
+
detail: `template de ${eventType}/${channel} existe mas não está aprovado`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const best = approved.reduce((a, b) => (specificity(b) > specificity(a) ? b : a));
|
|
47
|
+
return { ok: true, template: best };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Ordena as variáveis do consumidor na ordem que o template declara.
|
|
51
|
+
*
|
|
52
|
+
* Devolve falha quando falta alguma, em vez de substituir por vazio. Um template
|
|
53
|
+
* de cobrança com o valor em branco — "consta em aberto o valor de ." — chega ao
|
|
54
|
+
* cliente parecendo defeito do escritório, e o WhatsApp recusa a mensagem de
|
|
55
|
+
* qualquer forma quando um parâmetro posicional vem vazio.
|
|
56
|
+
*/
|
|
57
|
+
function orderVariables(template, values) {
|
|
58
|
+
const missing = template.variables.filter((name) => values[name] === undefined || values[name] === '');
|
|
59
|
+
if (missing.length > 0)
|
|
60
|
+
return { ok: false, missing: [...missing] };
|
|
61
|
+
return { ok: true, ordered: template.variables.map((name) => values[name]) };
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/communication/template.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AA8EH,0CAuBC;AAUD,wCASC;AA5DD;;;;;;GAMG;AACH,SAAS,WAAW,CAAC,CAAiB;IACpC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,eAAe,CACnC,KAAoB,EACpB,GAAyB,EACzB,OAAmB,EACnB,SAAiB,EACjB,MAAc;IAEd,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACpE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,qBAAqB,SAAS,IAAI,OAAO,EAAE,EAAE,CAAC;IACjG,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IAC5D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,cAAc;YACtB,MAAM,EAAE,eAAe,SAAS,IAAI,OAAO,+BAA+B;SAC3E,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,cAAc,CAC5B,QAAwB,EACxB,MAA8B;IAE9B,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CACvC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAC5D,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;IACpE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAE,CAAC,EAAE,CAAC;AAChF,CAAC"}
|