@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,161 @@
|
|
|
1
|
+
import { NotFoundError, ValidationError } from '@baruk/shared';
|
|
2
|
+
import { assertLiveProviderAllowed, readLiveRuntime } from './live-guard.js';
|
|
3
|
+
import { revealSecret } from '../vault/repository.js';
|
|
4
|
+
import { resolveBillingProvider } from './provider/registry.js';
|
|
5
|
+
const toAccount = (r) => ({
|
|
6
|
+
id: r.id,
|
|
7
|
+
provider: r.provider,
|
|
8
|
+
accountReference: r.account_reference,
|
|
9
|
+
environment: r.environment,
|
|
10
|
+
isPrimary: r.is_primary ?? false,
|
|
11
|
+
capabilities: Array.isArray(r.supported_capabilities)
|
|
12
|
+
? r.supported_capabilities
|
|
13
|
+
: [],
|
|
14
|
+
credentialRef: r.credential_ref,
|
|
15
|
+
webhookCredentialRef: r.webhook_credential_ref,
|
|
16
|
+
status: r.status,
|
|
17
|
+
});
|
|
18
|
+
/** Conta ativa do tenant. `null` quando o escritório ainda não conectou nenhuma. */
|
|
19
|
+
/**
|
|
20
|
+
* A conta pela qual o escritório OPERA.
|
|
21
|
+
*
|
|
22
|
+
* Antes era "a primeira conta ativa por data de criação". Isso funcionava
|
|
23
|
+
* enquanto só podia existir uma; com sandbox e produção coexistindo, viraria a
|
|
24
|
+
* pior forma de escolher para onde vai o dinheiro — implícita e dependente de
|
|
25
|
+
* ordem de inserção.
|
|
26
|
+
*
|
|
27
|
+
* Agora a escolha é uma MARCA explícita, e o banco garante que só há uma:
|
|
28
|
+
* `payment_provider_account_primary_uq`. Sem `LIMIT`, de propósito — se algum
|
|
29
|
+
* dia houvesse duas, o certo é o erro aparecer, não o sistema escolher sozinho.
|
|
30
|
+
*/
|
|
31
|
+
export async function getActiveProviderAccount(tx) {
|
|
32
|
+
const rows = await tx `
|
|
33
|
+
SELECT id, provider, account_reference, environment, supported_capabilities,
|
|
34
|
+
credential_ref, webhook_credential_ref, status, is_primary
|
|
35
|
+
FROM payment_provider_account
|
|
36
|
+
WHERE status = 'active' AND is_primary
|
|
37
|
+
`;
|
|
38
|
+
return rows[0] ? toAccount(rows[0]) : null;
|
|
39
|
+
}
|
|
40
|
+
/** Todas as contas vivas do escritório — o laboratório e a operação. */
|
|
41
|
+
export async function listProviderAccounts(tx) {
|
|
42
|
+
const rows = await tx `
|
|
43
|
+
SELECT id, provider, account_reference, environment, supported_capabilities,
|
|
44
|
+
credential_ref, webhook_credential_ref, status, is_primary
|
|
45
|
+
FROM payment_provider_account
|
|
46
|
+
WHERE status <> 'revoked'
|
|
47
|
+
ORDER BY environment, created_at
|
|
48
|
+
`;
|
|
49
|
+
return rows.map(toAccount);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Conta ativa de um AMBIENTE específico.
|
|
53
|
+
*
|
|
54
|
+
* Existe para quem sabe o que quer — um ensaio pede `sandbox` mesmo que a
|
|
55
|
+
* operação já esteja em produção. Nunca cai em outro ambiente por falta do
|
|
56
|
+
* pedido: sem conta naquele ambiente, devolve nulo.
|
|
57
|
+
*/
|
|
58
|
+
export async function getProviderAccountByEnvironment(tx, environment) {
|
|
59
|
+
const rows = await tx `
|
|
60
|
+
SELECT id, provider, account_reference, environment, supported_capabilities,
|
|
61
|
+
credential_ref, webhook_credential_ref, status, is_primary
|
|
62
|
+
FROM payment_provider_account
|
|
63
|
+
WHERE status = 'active' AND environment = ${environment}
|
|
64
|
+
`;
|
|
65
|
+
return rows[0] ? toAccount(rows[0]) : null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Promove uma conta a operacional — o ato de "entrar em produção".
|
|
69
|
+
*
|
|
70
|
+
* Explícito e reversível, em vez de efeito colateral de revogar o laboratório.
|
|
71
|
+
* A despromoção da anterior acontece na MESMA transação: entre um UPDATE e o
|
|
72
|
+
* outro existiria um instante com duas contas operacionais, e é justamente
|
|
73
|
+
* nesse instante que uma emissão escolheria errado.
|
|
74
|
+
*/
|
|
75
|
+
export async function setPrimaryProviderAccount(tx, id) {
|
|
76
|
+
const alvo = await tx `
|
|
77
|
+
SELECT provider FROM payment_provider_account
|
|
78
|
+
WHERE id = ${id} AND status = 'active'
|
|
79
|
+
`;
|
|
80
|
+
if (!alvo[0])
|
|
81
|
+
throw new NotFoundError('Conta de pagamento ativa não encontrada');
|
|
82
|
+
await tx `
|
|
83
|
+
UPDATE payment_provider_account SET is_primary = false, updated_at = now()
|
|
84
|
+
WHERE provider = ${alvo[0].provider} AND is_primary AND status <> 'revoked'
|
|
85
|
+
`;
|
|
86
|
+
await tx `
|
|
87
|
+
UPDATE payment_provider_account SET is_primary = true, updated_at = now()
|
|
88
|
+
WHERE id = ${id}
|
|
89
|
+
`;
|
|
90
|
+
const conta = await getProviderAccountById(tx, id);
|
|
91
|
+
if (!conta)
|
|
92
|
+
throw new NotFoundError('Conta de pagamento não encontrada');
|
|
93
|
+
return conta;
|
|
94
|
+
}
|
|
95
|
+
/** Conta por id — usada pelo webhook, que descobre o tenant pela URL. */
|
|
96
|
+
export async function getProviderAccountById(tx, id) {
|
|
97
|
+
const rows = await tx `
|
|
98
|
+
SELECT id, provider, account_reference, environment, supported_capabilities,
|
|
99
|
+
credential_ref, webhook_credential_ref, status, is_primary
|
|
100
|
+
FROM payment_provider_account WHERE id = ${id}
|
|
101
|
+
`;
|
|
102
|
+
return rows[0] ? toAccount(rows[0]) : null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* URL base do gateway conforme o ambiente declarado NA CONTA.
|
|
106
|
+
*
|
|
107
|
+
* A escolha não pode vir de env var do processo: dois tenants podem estar em
|
|
108
|
+
* ambientes diferentes na mesma instância — um escritório em homologação
|
|
109
|
+
* enquanto outro já cobra de verdade. Ambiente é atributo da conta.
|
|
110
|
+
*/
|
|
111
|
+
const BASE_URL = {
|
|
112
|
+
asaas: {
|
|
113
|
+
live: 'https://api.asaas.com/v3',
|
|
114
|
+
sandbox: 'https://api-sandbox.asaas.com/v3',
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Base do gateway para um par (provider, ambiente).
|
|
119
|
+
*
|
|
120
|
+
* Exportada porque a CONEXÃO da conta também precisa dela, e uma segunda cópia
|
|
121
|
+
* divergiria: foi assim que uma chave de sandbox chegou a ser validada contra
|
|
122
|
+
* produção — o adapter caía no default `live` e devolvia 401 com a credencial
|
|
123
|
+
* correta na mão.
|
|
124
|
+
*/
|
|
125
|
+
export function providerBaseUrl(provider, environment) {
|
|
126
|
+
return BASE_URL[provider]?.[environment];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Monta o adapter já apontado para a conta do tenant.
|
|
130
|
+
*
|
|
131
|
+
* `revealSecret` é a única forma de a credencial sair do Vault, e ela sai
|
|
132
|
+
* direto para dentro do adapter — não é devolvida, logada nem guardada em
|
|
133
|
+
* variável de módulo.
|
|
134
|
+
*/
|
|
135
|
+
export async function resolveProviderForTenant(tx, keyring, tenantId, opts = {}) {
|
|
136
|
+
const account = opts.account ?? (await getActiveProviderAccount(tx));
|
|
137
|
+
if (!account)
|
|
138
|
+
return null;
|
|
139
|
+
// Antes de a credencial sair do Vault: uma aplicação que não é produção não
|
|
140
|
+
// deve nem abrir conexão com a conta live — inclusive para receber webhook.
|
|
141
|
+
assertLiveProviderAllowed(account.environment, readLiveRuntime(), 'resolve');
|
|
142
|
+
if (!account.credentialRef) {
|
|
143
|
+
throw new ValidationError(`A conta de pagamento do escritório não tem credencial associada (provider "${account.provider}").`);
|
|
144
|
+
}
|
|
145
|
+
const { secret } = await revealSecret(tx, keyring, tenantId, account.credentialRef);
|
|
146
|
+
// O token de webhook é opcional na emissão e obrigatório na recepção: dá para
|
|
147
|
+
// emitir cobrança sem ele, mas a rota pública recusa tudo enquanto faltar.
|
|
148
|
+
const webhookSecret = account.webhookCredentialRef
|
|
149
|
+
? (await revealSecret(tx, keyring, tenantId, account.webhookCredentialRef)).secret
|
|
150
|
+
: undefined;
|
|
151
|
+
return {
|
|
152
|
+
account,
|
|
153
|
+
provider: resolveBillingProvider(account.provider, {
|
|
154
|
+
apiKey: secret,
|
|
155
|
+
baseUrl: providerBaseUrl(account.provider, account.environment),
|
|
156
|
+
webhookSecret,
|
|
157
|
+
fetchImpl: opts.fetchImpl,
|
|
158
|
+
}),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=provider-account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-account.js","sourceRoot":"","sources":["../../src/billing/provider-account.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Tx } from '../db/client.js';
|
|
2
|
+
import type { Keyring } from '../vault/crypto.js';
|
|
3
|
+
import type { ProviderAccountIdentity } from './provider/types.js';
|
|
4
|
+
import type { ProviderAccount } from './provider-account.js';
|
|
5
|
+
/**
|
|
6
|
+
* Conectar a conta de pagamento de um escritório.
|
|
7
|
+
*
|
|
8
|
+
* Este é o único caminho pelo qual uma credencial de gateway entra no sistema.
|
|
9
|
+
* Ele existe para que ninguém precise fazer `INSERT` com segredo na mão — e
|
|
10
|
+
* para que três verificações aconteçam SEMPRE, não quando alguém lembrar:
|
|
11
|
+
*
|
|
12
|
+
* 1. a credencial funciona (é usada de verdade contra o gateway);
|
|
13
|
+
* 2. a conta que ela abre é **identificada**, e não presumida pelo nome;
|
|
14
|
+
* 3. essa conta **não pertence a outro tenant** já conectado.
|
|
15
|
+
*
|
|
16
|
+
* A terceira é a que impede o pior desfecho possível deste produto: dois
|
|
17
|
+
* escritórios apontando para a mesma conta, e o dinheiro de um caindo na conta
|
|
18
|
+
* do outro. Nome de variável nunca provou titularidade — cinco chaves chamadas
|
|
19
|
+
* `ASAAS_<produto>_API_KEY` acabaram todas na mesma conta da Baruk.
|
|
20
|
+
*/
|
|
21
|
+
export interface ConnectProviderAccountInput {
|
|
22
|
+
provider: string;
|
|
23
|
+
/** Credencial de API. Entra, é usada e vai para o Vault — nunca é devolvida. */
|
|
24
|
+
apiKey: string;
|
|
25
|
+
/** Token que autentica o webhook. Sem ele a rota de recepção recusa tudo. */
|
|
26
|
+
webhookToken?: string | null;
|
|
27
|
+
environment: 'sandbox' | 'live';
|
|
28
|
+
capabilities?: string[];
|
|
29
|
+
/** Base do gateway; só para testes apontarem a um servidor local. */
|
|
30
|
+
baseUrl?: string;
|
|
31
|
+
fetchImpl?: typeof fetch;
|
|
32
|
+
}
|
|
33
|
+
export interface ConnectedAccount {
|
|
34
|
+
account: ProviderAccount;
|
|
35
|
+
identity: ProviderAccountIdentity;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Conta que a PLATAFORMA usa para cobrar os próprios assinantes.
|
|
39
|
+
*
|
|
40
|
+
* Quando informada, nenhum tenant pode conectar-se a ela. É a proteção contra o
|
|
41
|
+
* erro mais fácil de cometer: reaproveitar a chave que já estava à mão.
|
|
42
|
+
*/
|
|
43
|
+
export interface PlatformAccountGuard {
|
|
44
|
+
documentNumber?: string | null;
|
|
45
|
+
reference?: string | null;
|
|
46
|
+
}
|
|
47
|
+
export declare function connectProviderAccount(tx: Tx, keyring: Keyring, tenantId: string, input: ConnectProviderAccountInput, platform?: PlatformAccountGuard): Promise<ConnectedAccount>;
|
|
48
|
+
/** Revoga a conta. A credencial fica no Vault, marcada — histórico não se apaga. */
|
|
49
|
+
export declare function revokeProviderAccount(tx: Tx, accountId: string): Promise<number>;
|
|
50
|
+
/**
|
|
51
|
+
* Reconsulta a identidade da conta e atualiza o que estiver defasado.
|
|
52
|
+
*
|
|
53
|
+
* Existe por dois motivos concretos, os dois observados na conta da SC:
|
|
54
|
+
*
|
|
55
|
+
* - **a referência pode ter nascido nula** (o gateway não expunha id na época),
|
|
56
|
+
* e sem ela o guard que impede duas organizações de receberem na mesma conta
|
|
57
|
+
* fica inativo — o índice de unicidade é parcial;
|
|
58
|
+
* - **a credencial pode ter sido revogada do lado do gateway** sem ninguém
|
|
59
|
+
* avisar, e `last_validated_at` é a única forma de saber quando foi a última
|
|
60
|
+
* vez que ela comprovadamente funcionou.
|
|
61
|
+
*
|
|
62
|
+
* Não troca a credencial: só confirma de quem é a conta que ela abre.
|
|
63
|
+
*/
|
|
64
|
+
export declare function revalidateProviderAccount(tx: Tx, keyring: Keyring, tenantId: string, account: ProviderAccount, opts?: {
|
|
65
|
+
fetchImpl?: typeof fetch;
|
|
66
|
+
}): Promise<ProviderAccountIdentity>;
|
|
67
|
+
//# sourceMappingURL=provider-onboarding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-onboarding.d.ts","sourceRoot":"","sources":["../../src/billing/provider-onboarding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,uBAAuB,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,2BAA2B,EAClC,QAAQ,GAAE,oBAAyB,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAsG3B;AA6GD,oFAAoF;AACpF,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQtF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,eAAe,EACxB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAO,GACtC,OAAO,CAAC,uBAAuB,CAAC,CAmClC"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { ConflictError, ValidationError } from '@baruk/shared';
|
|
3
|
+
import { createCredential, revealSecret } from '../vault/repository.js';
|
|
4
|
+
import { resolveBillingProvider } from './provider/registry.js';
|
|
5
|
+
import { providerBaseUrl } from './provider-account.js';
|
|
6
|
+
export async function connectProviderAccount(tx, keyring, tenantId, input, platform = {}) {
|
|
7
|
+
const apiKey = input.apiKey.trim();
|
|
8
|
+
if (!apiKey)
|
|
9
|
+
throw new ValidationError('Credencial vazia.');
|
|
10
|
+
const provider = resolveBillingProvider(input.provider, {
|
|
11
|
+
apiKey,
|
|
12
|
+
// A base vem do AMBIENTE declarado, não do default do adapter. Sem isto,
|
|
13
|
+
// uma chave de sandbox é validada contra produção e volta 401 — o operador
|
|
14
|
+
// lê "credencial inválida" com a credencial certa na mão.
|
|
15
|
+
baseUrl: input.baseUrl ?? providerBaseUrl(input.provider, input.environment),
|
|
16
|
+
fetchImpl: input.fetchImpl,
|
|
17
|
+
});
|
|
18
|
+
if (!provider.describeAccount) {
|
|
19
|
+
throw new ValidationError(`O provider "${input.provider}" não sabe identificar a própria conta — conectar às cegas não é aceitável para dinheiro.`);
|
|
20
|
+
}
|
|
21
|
+
// A credencial é EXERCIDA aqui. Guardar sem usar significaria descobrir que
|
|
22
|
+
// ela não funciona na primeira cobrança de um cliente real.
|
|
23
|
+
const identity = await provider.describeAccount();
|
|
24
|
+
assertNotPlatformAccount(identity, platform);
|
|
25
|
+
// Conta do PRÓPRIO escritório: a RLS deixa ver, então dá para recusar com uma
|
|
26
|
+
// consulta limpa, sem provocar violação. Só o caso cross-tenant precisa do
|
|
27
|
+
// banco para ser detectado — e ele vem depois, isolado num savepoint.
|
|
28
|
+
// Por AMBIENTE, e não por provedor: duas contas do mesmo gateway em ambientes
|
|
29
|
+
// diferentes não são a mesma conta — têm credencial, endpoint e dinheiro
|
|
30
|
+
// distintos. Enquanto a checagem era por provedor, ativar produção exigia
|
|
31
|
+
// revogar o laboratório, e a decisão "vou cobrar de verdade" ficava amarrada a
|
|
32
|
+
// "vou perder onde ensaio".
|
|
33
|
+
const jaTem = await tx `
|
|
34
|
+
SELECT id FROM payment_provider_account
|
|
35
|
+
WHERE provider = ${input.provider} AND environment = ${input.environment}
|
|
36
|
+
AND status <> 'revoked' LIMIT 1
|
|
37
|
+
`;
|
|
38
|
+
if (jaTem[0]) {
|
|
39
|
+
throw new ConflictError(`Este escritório já tem uma conta ${input.provider} em ${input.environment}. ` +
|
|
40
|
+
'Revogue a atual antes de conectar outra neste ambiente.');
|
|
41
|
+
}
|
|
42
|
+
// A primeira conta do escritório nasce operacional; as seguintes nascem como
|
|
43
|
+
// laboratório. Promover é ato explícito — conectar produção não pode, sozinho,
|
|
44
|
+
// redirecionar o dinheiro.
|
|
45
|
+
const jaTemPrimaria = await tx `
|
|
46
|
+
SELECT id FROM payment_provider_account
|
|
47
|
+
WHERE provider = ${input.provider} AND is_primary AND status <> 'revoked' LIMIT 1
|
|
48
|
+
`;
|
|
49
|
+
const nasceOperacional = !jaTemPrimaria[0];
|
|
50
|
+
// A garantia de que nenhuma outra organização já usa esta conta é do BANCO
|
|
51
|
+
// (índice único em `provider, account_reference`), não de uma consulta aqui.
|
|
52
|
+
// Uma consulta não serviria: com RLS FORCE, `WHERE tenant_id <> atual`
|
|
53
|
+
// devolve sempre zero — a política esconde justamente a linha que a checagem
|
|
54
|
+
// precisaria encontrar. O guard pareceria proteger sem proteger.
|
|
55
|
+
const apiRef = await createCredential(tx, keyring, tenantId, {
|
|
56
|
+
name: credentialName(input.provider, input.environment, 'api'),
|
|
57
|
+
category: 'api_key',
|
|
58
|
+
secret: apiKey,
|
|
59
|
+
provider: input.provider,
|
|
60
|
+
// O metadata guarda de quem é a conta, para auditoria futura conseguir
|
|
61
|
+
// responder "esta chave abria qual conta?" sem precisar decifrá-la.
|
|
62
|
+
metadata: {
|
|
63
|
+
purpose: 'payment_provider_api_key',
|
|
64
|
+
accountName: identity.name,
|
|
65
|
+
accountReference: identity.reference,
|
|
66
|
+
environment: input.environment,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
const webhookRef = input.webhookToken?.trim()
|
|
70
|
+
? await createCredential(tx, keyring, tenantId, {
|
|
71
|
+
name: credentialName(input.provider, input.environment, 'webhook'),
|
|
72
|
+
category: 'api_key',
|
|
73
|
+
secret: input.webhookToken.trim(),
|
|
74
|
+
provider: input.provider,
|
|
75
|
+
metadata: { purpose: 'payment_provider_webhook_token', environment: input.environment },
|
|
76
|
+
})
|
|
77
|
+
: null;
|
|
78
|
+
const id = randomUUID();
|
|
79
|
+
await insertAccount(tx, id, input, identity, apiRef.id, webhookRef?.id ?? null, nasceOperacional);
|
|
80
|
+
return {
|
|
81
|
+
identity,
|
|
82
|
+
account: {
|
|
83
|
+
id,
|
|
84
|
+
provider: input.provider,
|
|
85
|
+
accountReference: identity.reference,
|
|
86
|
+
environment: input.environment,
|
|
87
|
+
capabilities: input.capabilities ?? ['pix', 'boleto'],
|
|
88
|
+
credentialRef: apiRef.id,
|
|
89
|
+
webhookCredentialRef: webhookRef?.id ?? null,
|
|
90
|
+
isPrimary: nasceOperacional,
|
|
91
|
+
status: 'active',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Insere a conta dentro de um SAVEPOINT.
|
|
97
|
+
*
|
|
98
|
+
* O savepoint não é zelo excessivo: uma violação de unicidade aborta a
|
|
99
|
+
* transação inteira, e a partir daí qualquer comando falha — inclusive os que o
|
|
100
|
+
* driver roda ao desfazer. O erro que chegaria ao usuário seria o do rollback,
|
|
101
|
+
* não o meu, e a rota devolveria 500 no lugar de uma explicação. Com o
|
|
102
|
+
* savepoint, só a tentativa de INSERT é desfeita e a mensagem certa sobrevive.
|
|
103
|
+
*
|
|
104
|
+
* O que se detecta aqui é o caso **cross-tenant**: a RLS esconde a conta de
|
|
105
|
+
* outro escritório, então nenhuma consulta encontraria o conflito — só o índice.
|
|
106
|
+
*/
|
|
107
|
+
async function insertAccount(tx, id, input, identity, credentialRef, webhookRef, nasceOperacional) {
|
|
108
|
+
try {
|
|
109
|
+
await tx.savepoint(async (sp) => {
|
|
110
|
+
await sp `
|
|
111
|
+
INSERT INTO payment_provider_account (
|
|
112
|
+
id, tenant_id, provider, account_reference, environment,
|
|
113
|
+
supported_capabilities, status, credential_ref, webhook_credential_ref,
|
|
114
|
+
last_validated_at, is_primary
|
|
115
|
+
) VALUES (
|
|
116
|
+
${id},
|
|
117
|
+
NULLIF(current_setting('app.current_tenant', true), '')::uuid,
|
|
118
|
+
${input.provider}, ${identity.reference}, ${input.environment},
|
|
119
|
+
${tx.json((input.capabilities ?? ['pix', 'boleto']))},
|
|
120
|
+
'active', ${credentialRef}, ${webhookRef}, now(), ${nasceOperacional}
|
|
121
|
+
)
|
|
122
|
+
RETURNING id
|
|
123
|
+
`;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
if (constraintOf(err) === 'payment_provider_account_reference_uq') {
|
|
128
|
+
throw new ConflictError('Esta conta de pagamento já está conectada a outra organização. ' +
|
|
129
|
+
'Duas organizações não podem receber na mesma conta.');
|
|
130
|
+
}
|
|
131
|
+
if (constraintOf(err) === 'payment_provider_account_provider_uq') {
|
|
132
|
+
throw new ConflictError(`Este escritório já tem uma conta ${input.provider} conectada. Revogue a atual antes de conectar outra.`);
|
|
133
|
+
}
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function constraintOf(err) {
|
|
138
|
+
const e = err;
|
|
139
|
+
return e?.constraint_name ?? e?.constraint ?? null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Recusa a conta da plataforma.
|
|
143
|
+
*
|
|
144
|
+
* Comparação por documento E por referência: o mesmo CNPJ pode ter mais de uma
|
|
145
|
+
* conta, e a mesma conta pode aparecer com referências diferentes conforme o
|
|
146
|
+
* endpoint. Bater em qualquer um dos dois basta para recusar — aqui, falso
|
|
147
|
+
* positivo custa um pedido de esclarecimento, e falso negativo custa o dinheiro
|
|
148
|
+
* de um escritório caindo na conta da Baruk.
|
|
149
|
+
*/
|
|
150
|
+
function assertNotPlatformAccount(identity, platform) {
|
|
151
|
+
const mesmoDoc = platform.documentNumber &&
|
|
152
|
+
identity.documentNumber &&
|
|
153
|
+
onlyDigits(platform.documentNumber) === onlyDigits(identity.documentNumber);
|
|
154
|
+
const mesmaRef = platform.reference && identity.reference && platform.reference === identity.reference;
|
|
155
|
+
if (mesmoDoc || mesmaRef) {
|
|
156
|
+
throw new ValidationError('Esta credencial abre a conta da plataforma, não a do escritório. ' +
|
|
157
|
+
'O dinheiro cobrado pelo escritório precisa cair na conta dele — ' +
|
|
158
|
+
'use uma credencial da conta do próprio escritório.');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Nome da credencial no Vault.
|
|
163
|
+
*
|
|
164
|
+
* O prefixo é canônico e legível; o sufixo é o que torna o nome **único**. O
|
|
165
|
+
* Vault exige nome único por tenant, e um nome fixo impediria o caso legítimo
|
|
166
|
+
* de desconectar uma conta e conectar outra — a credencial antiga continua
|
|
167
|
+
* existindo, marcada, porque histórico de credencial não se apaga.
|
|
168
|
+
*
|
|
169
|
+
* Quem procura por semântica não usa o nome: `provider` e `metadata.purpose`
|
|
170
|
+
* são os campos indexáveis para isso.
|
|
171
|
+
*/
|
|
172
|
+
function credentialName(provider, environment, kind) {
|
|
173
|
+
return `baruk-office-${provider}-${environment}-${kind}-${randomUUID().slice(0, 8)}`;
|
|
174
|
+
}
|
|
175
|
+
function onlyDigits(v) {
|
|
176
|
+
return v.replace(/\D/g, '');
|
|
177
|
+
}
|
|
178
|
+
/** Revoga a conta. A credencial fica no Vault, marcada — histórico não se apaga. */
|
|
179
|
+
export async function revokeProviderAccount(tx, accountId) {
|
|
180
|
+
const rows = await tx `
|
|
181
|
+
UPDATE payment_provider_account
|
|
182
|
+
SET status = 'revoked', revoked_at = now(), updated_at = now()
|
|
183
|
+
WHERE id = ${accountId} AND status <> 'revoked'
|
|
184
|
+
RETURNING id
|
|
185
|
+
`;
|
|
186
|
+
return rows.length;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Reconsulta a identidade da conta e atualiza o que estiver defasado.
|
|
190
|
+
*
|
|
191
|
+
* Existe por dois motivos concretos, os dois observados na conta da SC:
|
|
192
|
+
*
|
|
193
|
+
* - **a referência pode ter nascido nula** (o gateway não expunha id na época),
|
|
194
|
+
* e sem ela o guard que impede duas organizações de receberem na mesma conta
|
|
195
|
+
* fica inativo — o índice de unicidade é parcial;
|
|
196
|
+
* - **a credencial pode ter sido revogada do lado do gateway** sem ninguém
|
|
197
|
+
* avisar, e `last_validated_at` é a única forma de saber quando foi a última
|
|
198
|
+
* vez que ela comprovadamente funcionou.
|
|
199
|
+
*
|
|
200
|
+
* Não troca a credencial: só confirma de quem é a conta que ela abre.
|
|
201
|
+
*/
|
|
202
|
+
export async function revalidateProviderAccount(tx, keyring, tenantId, account, opts = {}) {
|
|
203
|
+
if (!account.credentialRef) {
|
|
204
|
+
throw new ValidationError('A conta não tem credencial associada.');
|
|
205
|
+
}
|
|
206
|
+
const { secret } = await revealSecret(tx, keyring, tenantId, account.credentialRef);
|
|
207
|
+
const provider = resolveBillingProvider(account.provider, {
|
|
208
|
+
apiKey: secret,
|
|
209
|
+
baseUrl: providerBaseUrl(account.provider, account.environment),
|
|
210
|
+
fetchImpl: opts.fetchImpl,
|
|
211
|
+
});
|
|
212
|
+
if (!provider.describeAccount) {
|
|
213
|
+
throw new ValidationError(`O provider "${account.provider}" não sabe identificar a própria conta.`);
|
|
214
|
+
}
|
|
215
|
+
const identity = await provider.describeAccount();
|
|
216
|
+
// A referência só é gravada quando falta. Sobrescrever uma referência
|
|
217
|
+
// existente com outra silenciosamente mudaria a identidade da conta que já
|
|
218
|
+
// está recebendo dinheiro — se divergir, é caso para o humano olhar.
|
|
219
|
+
if (!account.accountReference && identity.reference) {
|
|
220
|
+
await tx `
|
|
221
|
+
UPDATE payment_provider_account
|
|
222
|
+
SET account_reference = ${identity.reference}, last_validated_at = now(), updated_at = now()
|
|
223
|
+
WHERE id = ${account.id}
|
|
224
|
+
`;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
await tx `
|
|
228
|
+
UPDATE payment_provider_account
|
|
229
|
+
SET last_validated_at = now(), updated_at = now() WHERE id = ${account.id}
|
|
230
|
+
`;
|
|
231
|
+
}
|
|
232
|
+
return identity;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=provider-onboarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-onboarding.js","sourceRoot":"","sources":["../../src/billing/provider-onboarding.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,7 +42,11 @@ export interface ReceivableItemRecord {
|
|
|
42
42
|
serviceItemRef: string | null;
|
|
43
43
|
createdAt: string;
|
|
44
44
|
}
|
|
45
|
-
export type PaymentStatus = 'detected' | 'confirmed'
|
|
45
|
+
export type PaymentStatus = 'detected' | 'confirmed'
|
|
46
|
+
/** O dinheiro entrou e voltou ao pagador. */
|
|
47
|
+
| 'refunded'
|
|
48
|
+
/** O dinheiro nunca entrou: o registro de liquidação foi anulado na origem. */
|
|
49
|
+
| 'reversed';
|
|
46
50
|
export interface PaymentRecord {
|
|
47
51
|
id: string;
|
|
48
52
|
receivableId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receivable.d.ts","sourceRoot":"","sources":["../../src/billing/receivable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AAIH,MAAM,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"receivable.d.ts","sourceRoot":"","sources":["../../src/billing/receivable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Tx } from '../db/client.js';
|
|
2
|
+
import type { WebhookEvent } from './provider/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reconciliação — o webhook do gateway virando baixa no recebível.
|
|
5
|
+
*
|
|
6
|
+
* A rota que chama isto é pública. Toda a defesa mora aqui e no adapter:
|
|
7
|
+
* autenticação (adapter), deduplicação (esta função) e limite de efeito (só
|
|
8
|
+
* mexe no recebível apontado pela cobrança que o evento cita).
|
|
9
|
+
*
|
|
10
|
+
* Regra que atravessa o arquivo: **evento repetido não pode repetir efeito.**
|
|
11
|
+
* O gateway reenvia até receber 200, e vai reenviar depois de um timeout nosso
|
|
12
|
+
* mesmo tendo nós processado — do lado dele, a entrega falhou.
|
|
13
|
+
*/
|
|
14
|
+
export type ReconcileOutcome = 'duplicate' | 'charge_not_found' | 'already_paid' | 'paid' | 'refunded' | 'canceled' | 'overdue'
|
|
15
|
+
/**
|
|
16
|
+
* O evento contradiz a baixa que já está registrada, e nenhuma máquina deve
|
|
17
|
+
* decidir sozinha o que fazer. Marca para o humano e para.
|
|
18
|
+
*/
|
|
19
|
+
| 'needs_review'
|
|
20
|
+
/** A liquidação foi anulada na origem: o saldo voltou a existir. */
|
|
21
|
+
| 'reversed'
|
|
22
|
+
/** Nada havia para anular — evento repetido, ou anulação de algo nunca pago. */
|
|
23
|
+
| 'already_reversed' | 'ignored';
|
|
24
|
+
export interface ReconcileResult {
|
|
25
|
+
outcome: ReconcileOutcome;
|
|
26
|
+
receivableId: string | null;
|
|
27
|
+
chargeId: string | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Grava o evento e diz se ele é novo.
|
|
31
|
+
*
|
|
32
|
+
* O INSERT é a trava: quem consegue inserir processa, quem colide já foi
|
|
33
|
+
* processado por outro. Fazer `SELECT` antes e `INSERT` depois deixaria uma
|
|
34
|
+
* janela entre os dois — e webhook duplicado chega em rajada, exatamente dentro
|
|
35
|
+
* dessa janela.
|
|
36
|
+
*/
|
|
37
|
+
export declare function recordWebhookEvent(tx: Tx, input: {
|
|
38
|
+
tenantId: string | null;
|
|
39
|
+
providerAccountId: string | null;
|
|
40
|
+
provider: string;
|
|
41
|
+
eventId: string;
|
|
42
|
+
eventType: string;
|
|
43
|
+
payload: unknown;
|
|
44
|
+
}): Promise<{
|
|
45
|
+
id: string;
|
|
46
|
+
isNew: boolean;
|
|
47
|
+
}>;
|
|
48
|
+
export declare function markWebhookProcessed(tx: Tx, id: string, status: 'processed' | 'ignored' | 'failed'): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Aplica o evento normalizado ao recebível.
|
|
51
|
+
*
|
|
52
|
+
* Chamada DEPOIS de `recordWebhookEvent` ter dito que o evento é novo. Ainda
|
|
53
|
+
* assim confere o estado do recebível antes de baixar: dois eventos distintos
|
|
54
|
+
* (`CONFIRMED` e `RECEIVED`) descrevem o mesmo pagamento, passam os dois pelo
|
|
55
|
+
* dedup por serem eventos diferentes, e baixariam duas vezes o mesmo dinheiro.
|
|
56
|
+
*/
|
|
57
|
+
export declare function applyWebhookEvent(tx: Tx, event: WebhookEvent): Promise<ReconcileResult>;
|
|
58
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/billing/reconcile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEvE;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,kBAAkB,GAClB,cAAc,GACd,MAAM,GACN,UAAU,GACV,UAAU,GACV,SAAS;AACX;;;GAGG;GACD,cAAc;AAChB,oEAAoE;GAClE,UAAU;AACZ,gFAAgF;GAC9E,kBAAkB,GAClB,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB,GACA,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAazC;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,GACzC,OAAO,CAAC,IAAI,CAAC,CAIf;AAUD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CA0D7F"}
|