@baruk/core 0.4.2 → 0.6.0
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 +4 -4
- package/CHANGELOG.md +42 -0
- package/dist/audit/repository.d.ts +33 -1
- package/dist/audit/repository.d.ts.map +1 -1
- package/dist/audit/repository.js +41 -7
- package/dist/audit/repository.js.map +1 -1
- package/dist/auth/service.d.ts +21 -0
- package/dist/auth/service.d.ts.map +1 -1
- package/dist/auth/service.js +46 -1
- package/dist/auth/service.js.map +1 -1
- package/dist/billing/ar-repository.d.ts +41 -1
- package/dist/billing/ar-repository.d.ts.map +1 -1
- package/dist/billing/ar-repository.js +82 -6
- package/dist/billing/ar-repository.js.map +1 -1
- package/dist/billing/provider-account.d.ts +38 -0
- package/dist/billing/provider-account.d.ts.map +1 -1
- package/dist/billing/provider-account.js +58 -2
- package/dist/billing/provider-account.js.map +1 -1
- package/dist/billing/repository.d.ts +44 -0
- package/dist/billing/repository.d.ts.map +1 -1
- package/dist/billing/repository.js +49 -5
- package/dist/billing/repository.js.map +1 -1
- package/dist/cjs/audit/repository.js +41 -7
- package/dist/cjs/audit/repository.js.map +1 -1
- package/dist/cjs/auth/service.js +46 -1
- package/dist/cjs/auth/service.js.map +1 -1
- package/dist/cjs/billing/ar-repository.js +82 -6
- package/dist/cjs/billing/ar-repository.js.map +1 -1
- package/dist/cjs/billing/provider-account.js +60 -1
- package/dist/cjs/billing/provider-account.js.map +1 -1
- package/dist/cjs/billing/repository.js +51 -5
- package/dist/cjs/billing/repository.js.map +1 -1
- package/dist/cjs/clients/ibge.js +117 -0
- package/dist/cjs/clients/ibge.js.map +1 -0
- package/dist/cjs/clients/registry/http.js +157 -0
- package/dist/cjs/clients/registry/http.js.map +1 -0
- package/dist/cjs/clients/registry/ibge-municipios.js +28 -0
- package/dist/cjs/clients/registry/ibge-municipios.js.map +1 -0
- package/dist/cjs/clients/registry/ibge.js +63 -0
- package/dist/cjs/clients/registry/ibge.js.map +1 -0
- package/dist/cjs/clients/registry/lookup.js +191 -0
- package/dist/cjs/clients/registry/lookup.js.map +1 -0
- package/dist/cjs/clients/registry/provider.js +34 -0
- package/dist/cjs/clients/registry/provider.js.map +1 -0
- package/dist/cjs/clients/registry/resolve.js +47 -0
- package/dist/cjs/clients/registry/resolve.js.map +1 -0
- package/dist/cjs/clients/registry/serpro.js +149 -0
- package/dist/cjs/clients/registry/serpro.js.map +1 -0
- package/dist/cjs/clients/registry/service.js +230 -0
- package/dist/cjs/clients/registry/service.js.map +1 -0
- package/dist/cjs/clients/registry/synthetic.js +165 -0
- package/dist/cjs/clients/registry/synthetic.js.map +1 -0
- package/dist/cjs/clients/repository.js +190 -9
- package/dist/cjs/clients/repository.js.map +1 -1
- package/dist/cjs/collection/branding.js +190 -0
- package/dist/cjs/collection/branding.js.map +1 -1
- package/dist/cjs/collection/clearance-store.js +74 -0
- package/dist/cjs/collection/clearance-store.js.map +1 -0
- package/dist/cjs/collection/communication-runtime.js +65 -2
- package/dist/cjs/collection/communication-runtime.js.map +1 -1
- package/dist/cjs/collection/engine.js +20 -0
- package/dist/cjs/collection/engine.js.map +1 -1
- package/dist/cjs/collection/policy.js +29 -1
- package/dist/cjs/collection/policy.js.map +1 -1
- package/dist/cjs/communication/clearance.js +18 -0
- package/dist/cjs/communication/clearance.js.map +1 -0
- package/dist/cjs/communication/dry-run-scenario.js +5 -0
- package/dist/cjs/communication/dry-run-scenario.js.map +1 -1
- package/dist/cjs/communication/engine.js +12 -0
- package/dist/cjs/communication/engine.js.map +1 -1
- package/dist/cjs/communication/policy.js.map +1 -1
- package/dist/cjs/competence/business-days.js +155 -0
- package/dist/cjs/competence/business-days.js.map +1 -0
- package/dist/cjs/competence/catalog-validation.js +174 -0
- package/dist/cjs/competence/catalog-validation.js.map +1 -0
- package/dist/cjs/competence/obligation-preview.js +190 -0
- package/dist/cjs/competence/obligation-preview.js.map +1 -0
- package/dist/cjs/competence/repository.js +330 -17
- package/dist/cjs/competence/repository.js.map +1 -1
- package/dist/cjs/dashboard/pilot-panel.js +90 -0
- package/dist/cjs/dashboard/pilot-panel.js.map +1 -0
- package/dist/cjs/dashboard/repository.js +11 -1
- package/dist/cjs/dashboard/repository.js.map +1 -1
- package/dist/cjs/db/client.js +17 -11
- package/dist/cjs/db/client.js.map +1 -1
- package/dist/cjs/db/provision-e2e-identity.js +116 -0
- package/dist/cjs/db/provision-e2e-identity.js.map +1 -0
- package/dist/cjs/fiscal/applicability.js +164 -0
- package/dist/cjs/fiscal/applicability.js.map +1 -0
- package/dist/cjs/fiscal/collection/authorization.js +186 -0
- package/dist/cjs/fiscal/collection/authorization.js.map +1 -0
- package/dist/cjs/fiscal/collection/competence.js +97 -0
- package/dist/cjs/fiscal/collection/competence.js.map +1 -0
- package/dist/cjs/fiscal/collection/first-contact.js +204 -0
- package/dist/cjs/fiscal/collection/first-contact.js.map +1 -0
- package/dist/cjs/fiscal/collection/plan.js +122 -0
- package/dist/cjs/fiscal/collection/plan.js.map +1 -0
- package/dist/cjs/fiscal/conditions.js +198 -0
- package/dist/cjs/fiscal/conditions.js.map +1 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-contract.js +390 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-contract.js.map +1 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-endpoint.js +108 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-endpoint.js.map +1 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-envelope.js +220 -0
- package/dist/cjs/fiscal/contracts/nfse-adn-envelope.js.map +1 -0
- package/dist/cjs/fiscal/coverage/model.js +137 -0
- package/dist/cjs/fiscal/coverage/model.js.map +1 -0
- package/dist/cjs/fiscal/coverage/requests.js +99 -0
- package/dist/cjs/fiscal/coverage/requests.js.map +1 -0
- package/dist/cjs/fiscal/credentials/inspect.js +182 -0
- package/dist/cjs/fiscal/credentials/inspect.js.map +1 -0
- package/dist/cjs/fiscal/credentials/material.js +168 -0
- package/dist/cjs/fiscal/credentials/material.js.map +1 -0
- package/dist/cjs/fiscal/credentials/onboarding.js +266 -0
- package/dist/cjs/fiscal/credentials/onboarding.js.map +1 -0
- package/dist/cjs/fiscal/credentials/readiness.js +190 -0
- package/dist/cjs/fiscal/credentials/readiness.js.map +1 -0
- package/dist/cjs/fiscal/eligibility.js +199 -0
- package/dist/cjs/fiscal/eligibility.js.map +1 -0
- package/dist/cjs/fiscal/enrollment.js +134 -0
- package/dist/cjs/fiscal/enrollment.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/__fixtures__/nfse.js +128 -0
- package/dist/cjs/fiscal/ingestion/__fixtures__/nfse.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/adn-transport.js +229 -0
- package/dist/cjs/fiscal/ingestion/adn-transport.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/direction.js +36 -0
- package/dist/cjs/fiscal/ingestion/direction.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/nfse-adn.js +228 -0
- package/dist/cjs/fiscal/ingestion/nfse-adn.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/pipeline.js +704 -0
- package/dist/cjs/fiscal/ingestion/pipeline.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/provider.js +51 -0
- package/dist/cjs/fiscal/ingestion/provider.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/repository.js +132 -0
- package/dist/cjs/fiscal/ingestion/repository.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/synthetic-provider.js +103 -0
- package/dist/cjs/fiscal/ingestion/synthetic-provider.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport-types.js +13 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport-types.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport.js +61 -0
- package/dist/cjs/fiscal/ingestion/synthetic-transport.js.map +1 -0
- package/dist/cjs/fiscal/ingestion/xml-reader.js +121 -0
- package/dist/cjs/fiscal/ingestion/xml-reader.js.map +1 -0
- package/dist/cjs/fiscal/repository.js +470 -0
- package/dist/cjs/fiscal/repository.js.map +1 -0
- package/dist/cjs/fiscal/sync/circuit.js +124 -0
- package/dist/cjs/fiscal/sync/circuit.js.map +1 -0
- package/dist/cjs/fiscal/sync/intervention.js +140 -0
- package/dist/cjs/fiscal/sync/intervention.js.map +1 -0
- package/dist/cjs/fiscal/sync/lease.js +146 -0
- package/dist/cjs/fiscal/sync/lease.js.map +1 -0
- package/dist/cjs/fiscal/sync/observability.js +244 -0
- package/dist/cjs/fiscal/sync/observability.js.map +1 -0
- package/dist/cjs/fiscal/sync/orchestrator.js +490 -0
- package/dist/cjs/fiscal/sync/orchestrator.js.map +1 -0
- package/dist/cjs/fiscal/sync/policy.js +143 -0
- package/dist/cjs/fiscal/sync/policy.js.map +1 -0
- package/dist/cjs/fiscal/sync/reprocess.js +241 -0
- package/dist/cjs/fiscal/sync/reprocess.js.map +1 -0
- package/dist/cjs/fiscal/sync/retry.js +183 -0
- package/dist/cjs/fiscal/sync/retry.js.map +1 -0
- package/dist/cjs/fiscal/sync/secret-boundary.js +123 -0
- package/dist/cjs/fiscal/sync/secret-boundary.js.map +1 -0
- package/dist/cjs/fiscal/transport/https.js +309 -0
- package/dist/cjs/fiscal/transport/https.js.map +1 -0
- package/dist/cjs/fiscal/transport/synthetic-tls.js +380 -0
- package/dist/cjs/fiscal/transport/synthetic-tls.js.map +1 -0
- package/dist/cjs/fiscal/transport/types.js +93 -0
- package/dist/cjs/fiscal/transport/types.js.map +1 -0
- package/dist/cjs/import/br-documents.js +85 -0
- package/dist/cjs/import/br-documents.js.map +1 -0
- package/dist/cjs/import/clients-import.js +347 -40
- package/dist/cjs/import/clients-import.js.map +1 -1
- package/dist/cjs/index.js +461 -73
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/legal/documents.js +164 -19
- package/dist/cjs/legal/documents.js.map +1 -1
- package/dist/cjs/legal/index.js +3 -1
- package/dist/cjs/legal/index.js.map +1 -1
- package/dist/cjs/legal/types.js.map +1 -1
- package/dist/cjs/onboarding/persistence.js +4 -4
- package/dist/cjs/onboarding/persistence.js.map +1 -1
- package/dist/cjs/pilot/go-live-checklist.js +212 -0
- package/dist/cjs/pilot/go-live-checklist.js.map +1 -0
- package/dist/cjs/pilot/milestone.js +79 -0
- package/dist/cjs/pilot/milestone.js.map +1 -0
- package/dist/cjs/platform/capabilities.js +173 -0
- package/dist/cjs/platform/capabilities.js.map +1 -0
- package/dist/cjs/platform/job-contract.js +411 -0
- package/dist/cjs/platform/job-contract.js.map +1 -0
- package/dist/cjs/rbac/catalog.js +110 -0
- package/dist/cjs/rbac/catalog.js.map +1 -1
- package/dist/cjs/subscription-billing/index.js +9 -1
- package/dist/cjs/subscription-billing/index.js.map +1 -1
- package/dist/cjs/subscription-billing/platform-exemption.js +121 -0
- package/dist/cjs/subscription-billing/platform-exemption.js.map +1 -0
- package/dist/cjs/subscription-billing/service.js +246 -78
- package/dist/cjs/subscription-billing/service.js.map +1 -1
- package/dist/cjs/tenancy/features.js +131 -0
- package/dist/cjs/tenancy/features.js.map +1 -0
- package/dist/cjs/tenancy/settings.js +224 -0
- package/dist/cjs/tenancy/settings.js.map +1 -0
- package/dist/cjs/users/repository.js +24 -1
- package/dist/cjs/users/repository.js.map +1 -1
- package/dist/cjs/vault/repository.js +92 -5
- package/dist/cjs/vault/repository.js.map +1 -1
- package/dist/clients/ibge.d.ts +17 -0
- package/dist/clients/ibge.d.ts.map +1 -0
- package/dist/clients/ibge.js +112 -0
- package/dist/clients/ibge.js.map +1 -0
- package/dist/clients/registry/http.d.ts +61 -0
- package/dist/clients/registry/http.d.ts.map +1 -0
- package/dist/clients/registry/http.js +151 -0
- package/dist/clients/registry/http.js.map +1 -0
- package/dist/clients/registry/ibge-municipios.d.ts +25 -0
- package/dist/clients/registry/ibge-municipios.d.ts.map +1 -0
- package/dist/clients/registry/ibge-municipios.js +25 -0
- package/dist/clients/registry/ibge-municipios.js.map +1 -0
- package/dist/clients/registry/ibge.d.ts +62 -0
- package/dist/clients/registry/ibge.d.ts.map +1 -0
- package/dist/clients/registry/ibge.js +57 -0
- package/dist/clients/registry/ibge.js.map +1 -0
- package/dist/clients/registry/lookup.d.ts +94 -0
- package/dist/clients/registry/lookup.d.ts.map +1 -0
- package/dist/clients/registry/lookup.js +184 -0
- package/dist/clients/registry/lookup.js.map +1 -0
- package/dist/clients/registry/provider.d.ts +124 -0
- package/dist/clients/registry/provider.d.ts.map +1 -0
- package/dist/clients/registry/provider.js +39 -0
- package/dist/clients/registry/provider.js.map +1 -0
- package/dist/clients/registry/resolve.d.ts +36 -0
- package/dist/clients/registry/resolve.d.ts.map +1 -0
- package/dist/clients/registry/resolve.js +44 -0
- package/dist/clients/registry/resolve.js.map +1 -0
- package/dist/clients/registry/serpro.d.ts +57 -0
- package/dist/clients/registry/serpro.d.ts.map +1 -0
- package/dist/clients/registry/serpro.js +143 -0
- package/dist/clients/registry/serpro.js.map +1 -0
- package/dist/clients/registry/service.d.ts +59 -0
- package/dist/clients/registry/service.d.ts.map +1 -0
- package/dist/clients/registry/service.js +225 -0
- package/dist/clients/registry/service.js.map +1 -0
- package/dist/clients/registry/synthetic.d.ts +30 -0
- package/dist/clients/registry/synthetic.d.ts.map +1 -0
- package/dist/clients/registry/synthetic.js +161 -0
- package/dist/clients/registry/synthetic.js.map +1 -0
- package/dist/clients/repository.d.ts +158 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +186 -9
- package/dist/clients/repository.js.map +1 -1
- package/dist/collection/branding.d.ts +65 -0
- package/dist/collection/branding.d.ts.map +1 -1
- package/dist/collection/branding.js +186 -0
- package/dist/collection/branding.js.map +1 -1
- package/dist/collection/clearance-store.d.ts +39 -0
- package/dist/collection/clearance-store.d.ts.map +1 -0
- package/dist/collection/clearance-store.js +69 -0
- package/dist/collection/clearance-store.js.map +1 -0
- package/dist/collection/communication-runtime.d.ts +37 -0
- package/dist/collection/communication-runtime.d.ts.map +1 -1
- package/dist/collection/communication-runtime.js +63 -1
- package/dist/collection/communication-runtime.js.map +1 -1
- package/dist/collection/engine.d.ts +23 -0
- package/dist/collection/engine.d.ts.map +1 -1
- package/dist/collection/engine.js +20 -0
- package/dist/collection/engine.js.map +1 -1
- package/dist/collection/policy.d.ts +25 -0
- package/dist/collection/policy.d.ts.map +1 -1
- package/dist/collection/policy.js +27 -0
- package/dist/collection/policy.js.map +1 -1
- package/dist/communication/clearance.d.ts +53 -0
- package/dist/communication/clearance.d.ts.map +1 -0
- package/dist/communication/clearance.js +15 -0
- package/dist/communication/clearance.js.map +1 -0
- package/dist/communication/dry-run-scenario.d.ts.map +1 -1
- package/dist/communication/dry-run-scenario.js +5 -0
- package/dist/communication/dry-run-scenario.js.map +1 -1
- package/dist/communication/engine.d.ts +10 -0
- package/dist/communication/engine.d.ts.map +1 -1
- package/dist/communication/engine.js +12 -0
- package/dist/communication/engine.js.map +1 -1
- package/dist/communication/policy.d.ts +16 -0
- package/dist/communication/policy.d.ts.map +1 -1
- package/dist/communication/policy.js.map +1 -1
- package/dist/competence/business-days.d.ts +51 -0
- package/dist/competence/business-days.d.ts.map +1 -0
- package/dist/competence/business-days.js +145 -0
- package/dist/competence/business-days.js.map +1 -0
- package/dist/competence/catalog-validation.d.ts +86 -0
- package/dist/competence/catalog-validation.d.ts.map +1 -0
- package/dist/competence/catalog-validation.js +168 -0
- package/dist/competence/catalog-validation.js.map +1 -0
- package/dist/competence/obligation-preview.d.ts +103 -0
- package/dist/competence/obligation-preview.d.ts.map +1 -0
- package/dist/competence/obligation-preview.js +184 -0
- package/dist/competence/obligation-preview.js.map +1 -0
- package/dist/competence/repository.d.ts +139 -1
- package/dist/competence/repository.d.ts.map +1 -1
- package/dist/competence/repository.js +325 -17
- package/dist/competence/repository.js.map +1 -1
- package/dist/dashboard/pilot-panel.d.ts +100 -0
- package/dist/dashboard/pilot-panel.d.ts.map +1 -0
- package/dist/dashboard/pilot-panel.js +87 -0
- package/dist/dashboard/pilot-panel.js.map +1 -0
- package/dist/dashboard/repository.d.ts.map +1 -1
- package/dist/dashboard/repository.js +11 -1
- package/dist/dashboard/repository.js.map +1 -1
- package/dist/db/client.d.ts +45 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +16 -11
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrate.d.ts +36 -1
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +199 -32
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/provision-e2e-identity.d.ts +2 -0
- package/dist/db/provision-e2e-identity.d.ts.map +1 -0
- package/dist/db/provision-e2e-identity.js +114 -0
- package/dist/db/provision-e2e-identity.js.map +1 -0
- package/dist/fiscal/applicability.d.ts +73 -0
- package/dist/fiscal/applicability.d.ts.map +1 -0
- package/dist/fiscal/applicability.js +160 -0
- package/dist/fiscal/applicability.js.map +1 -0
- package/dist/fiscal/collection/authorization.d.ts +152 -0
- package/dist/fiscal/collection/authorization.d.ts.map +1 -0
- package/dist/fiscal/collection/authorization.js +178 -0
- package/dist/fiscal/collection/authorization.js.map +1 -0
- package/dist/fiscal/collection/competence.d.ts +66 -0
- package/dist/fiscal/collection/competence.d.ts.map +1 -0
- package/dist/fiscal/collection/competence.js +90 -0
- package/dist/fiscal/collection/competence.js.map +1 -0
- package/dist/fiscal/collection/first-contact.d.ts +103 -0
- package/dist/fiscal/collection/first-contact.d.ts.map +1 -0
- package/dist/fiscal/collection/first-contact.js +201 -0
- package/dist/fiscal/collection/first-contact.js.map +1 -0
- package/dist/fiscal/collection/plan.d.ts +74 -0
- package/dist/fiscal/collection/plan.d.ts.map +1 -0
- package/dist/fiscal/collection/plan.js +119 -0
- package/dist/fiscal/collection/plan.js.map +1 -0
- package/dist/fiscal/conditions.d.ts +99 -0
- package/dist/fiscal/conditions.d.ts.map +1 -0
- package/dist/fiscal/conditions.js +190 -0
- package/dist/fiscal/conditions.js.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-contract.d.ts +315 -0
- package/dist/fiscal/contracts/nfse-adn-contract.d.ts.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-contract.js +386 -0
- package/dist/fiscal/contracts/nfse-adn-contract.js.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.d.ts +13 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.d.ts.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.js +103 -0
- package/dist/fiscal/contracts/nfse-adn-endpoint.js.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.d.ts +77 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.d.ts.map +1 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.js +215 -0
- package/dist/fiscal/contracts/nfse-adn-envelope.js.map +1 -0
- package/dist/fiscal/coverage/model.d.ts +114 -0
- package/dist/fiscal/coverage/model.d.ts.map +1 -0
- package/dist/fiscal/coverage/model.js +130 -0
- package/dist/fiscal/coverage/model.js.map +1 -0
- package/dist/fiscal/coverage/requests.d.ts +70 -0
- package/dist/fiscal/coverage/requests.d.ts.map +1 -0
- package/dist/fiscal/coverage/requests.js +95 -0
- package/dist/fiscal/coverage/requests.js.map +1 -0
- package/dist/fiscal/credentials/inspect.d.ts +114 -0
- package/dist/fiscal/credentials/inspect.d.ts.map +1 -0
- package/dist/fiscal/credentials/inspect.js +178 -0
- package/dist/fiscal/credentials/inspect.js.map +1 -0
- package/dist/fiscal/credentials/material.d.ts +81 -0
- package/dist/fiscal/credentials/material.d.ts.map +1 -0
- package/dist/fiscal/credentials/material.js +164 -0
- package/dist/fiscal/credentials/material.js.map +1 -0
- package/dist/fiscal/credentials/onboarding.d.ts +119 -0
- package/dist/fiscal/credentials/onboarding.d.ts.map +1 -0
- package/dist/fiscal/credentials/onboarding.js +259 -0
- package/dist/fiscal/credentials/onboarding.js.map +1 -0
- package/dist/fiscal/credentials/readiness.d.ts +119 -0
- package/dist/fiscal/credentials/readiness.d.ts.map +1 -0
- package/dist/fiscal/credentials/readiness.js +186 -0
- package/dist/fiscal/credentials/readiness.js.map +1 -0
- package/dist/fiscal/eligibility.d.ts +106 -0
- package/dist/fiscal/eligibility.d.ts.map +1 -0
- package/dist/fiscal/eligibility.js +194 -0
- package/dist/fiscal/eligibility.js.map +1 -0
- package/dist/fiscal/enrollment.d.ts +91 -0
- package/dist/fiscal/enrollment.d.ts.map +1 -0
- package/dist/fiscal/enrollment.js +126 -0
- package/dist/fiscal/enrollment.js.map +1 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.d.ts +57 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.d.ts.map +1 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.js +121 -0
- package/dist/fiscal/ingestion/__fixtures__/nfse.js.map +1 -0
- package/dist/fiscal/ingestion/adn-transport.d.ts +123 -0
- package/dist/fiscal/ingestion/adn-transport.d.ts.map +1 -0
- package/dist/fiscal/ingestion/adn-transport.js +220 -0
- package/dist/fiscal/ingestion/adn-transport.js.map +1 -0
- package/dist/fiscal/ingestion/direction.d.ts +60 -0
- package/dist/fiscal/ingestion/direction.d.ts.map +1 -0
- package/dist/fiscal/ingestion/direction.js +32 -0
- package/dist/fiscal/ingestion/direction.js.map +1 -0
- package/dist/fiscal/ingestion/nfse-adn.d.ts +91 -0
- package/dist/fiscal/ingestion/nfse-adn.d.ts.map +1 -0
- package/dist/fiscal/ingestion/nfse-adn.js +222 -0
- package/dist/fiscal/ingestion/nfse-adn.js.map +1 -0
- package/dist/fiscal/ingestion/pipeline.d.ts +168 -0
- package/dist/fiscal/ingestion/pipeline.d.ts.map +1 -0
- package/dist/fiscal/ingestion/pipeline.js +699 -0
- package/dist/fiscal/ingestion/pipeline.js.map +1 -0
- package/dist/fiscal/ingestion/provider.d.ts +206 -0
- package/dist/fiscal/ingestion/provider.d.ts.map +1 -0
- package/dist/fiscal/ingestion/provider.js +47 -0
- package/dist/fiscal/ingestion/provider.js.map +1 -0
- package/dist/fiscal/ingestion/repository.d.ts +82 -0
- package/dist/fiscal/ingestion/repository.d.ts.map +1 -0
- package/dist/fiscal/ingestion/repository.js +127 -0
- package/dist/fiscal/ingestion/repository.js.map +1 -0
- package/dist/fiscal/ingestion/synthetic-provider.d.ts +92 -0
- package/dist/fiscal/ingestion/synthetic-provider.d.ts.map +1 -0
- package/dist/fiscal/ingestion/synthetic-provider.js +99 -0
- package/dist/fiscal/ingestion/synthetic-provider.js.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.d.ts +19 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.d.ts.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.js +9 -0
- package/dist/fiscal/ingestion/synthetic-transport-types.js.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport.d.ts +55 -0
- package/dist/fiscal/ingestion/synthetic-transport.d.ts.map +1 -0
- package/dist/fiscal/ingestion/synthetic-transport.js +57 -0
- package/dist/fiscal/ingestion/synthetic-transport.js.map +1 -0
- package/dist/fiscal/ingestion/xml-reader.d.ts +55 -0
- package/dist/fiscal/ingestion/xml-reader.d.ts.map +1 -0
- package/dist/fiscal/ingestion/xml-reader.js +112 -0
- package/dist/fiscal/ingestion/xml-reader.js.map +1 -0
- package/dist/fiscal/repository.d.ts +220 -0
- package/dist/fiscal/repository.d.ts.map +1 -0
- package/dist/fiscal/repository.js +449 -0
- package/dist/fiscal/repository.js.map +1 -0
- package/dist/fiscal/sync/circuit.d.ts +86 -0
- package/dist/fiscal/sync/circuit.d.ts.map +1 -0
- package/dist/fiscal/sync/circuit.js +118 -0
- package/dist/fiscal/sync/circuit.js.map +1 -0
- package/dist/fiscal/sync/intervention.d.ts +81 -0
- package/dist/fiscal/sync/intervention.d.ts.map +1 -0
- package/dist/fiscal/sync/intervention.js +135 -0
- package/dist/fiscal/sync/intervention.js.map +1 -0
- package/dist/fiscal/sync/lease.d.ts +118 -0
- package/dist/fiscal/sync/lease.d.ts.map +1 -0
- package/dist/fiscal/sync/lease.js +139 -0
- package/dist/fiscal/sync/lease.js.map +1 -0
- package/dist/fiscal/sync/observability.d.ts +148 -0
- package/dist/fiscal/sync/observability.d.ts.map +1 -0
- package/dist/fiscal/sync/observability.js +239 -0
- package/dist/fiscal/sync/observability.js.map +1 -0
- package/dist/fiscal/sync/orchestrator.d.ts +132 -0
- package/dist/fiscal/sync/orchestrator.d.ts.map +1 -0
- package/dist/fiscal/sync/orchestrator.js +487 -0
- package/dist/fiscal/sync/orchestrator.js.map +1 -0
- package/dist/fiscal/sync/policy.d.ts +87 -0
- package/dist/fiscal/sync/policy.d.ts.map +1 -0
- package/dist/fiscal/sync/policy.js +136 -0
- package/dist/fiscal/sync/policy.js.map +1 -0
- package/dist/fiscal/sync/reprocess.d.ts +76 -0
- package/dist/fiscal/sync/reprocess.d.ts.map +1 -0
- package/dist/fiscal/sync/reprocess.js +237 -0
- package/dist/fiscal/sync/reprocess.js.map +1 -0
- package/dist/fiscal/sync/retry.d.ts +82 -0
- package/dist/fiscal/sync/retry.d.ts.map +1 -0
- package/dist/fiscal/sync/retry.js +176 -0
- package/dist/fiscal/sync/retry.js.map +1 -0
- package/dist/fiscal/sync/secret-boundary.d.ts +169 -0
- package/dist/fiscal/sync/secret-boundary.d.ts.map +1 -0
- package/dist/fiscal/sync/secret-boundary.js +116 -0
- package/dist/fiscal/sync/secret-boundary.js.map +1 -0
- package/dist/fiscal/transport/https.d.ts +86 -0
- package/dist/fiscal/transport/https.d.ts.map +1 -0
- package/dist/fiscal/transport/https.js +303 -0
- package/dist/fiscal/transport/https.js.map +1 -0
- package/dist/fiscal/transport/synthetic-tls.d.ts +99 -0
- package/dist/fiscal/transport/synthetic-tls.d.ts.map +1 -0
- package/dist/fiscal/transport/synthetic-tls.js +374 -0
- package/dist/fiscal/transport/synthetic-tls.js.map +1 -0
- package/dist/fiscal/transport/types.d.ts +134 -0
- package/dist/fiscal/transport/types.d.ts.map +1 -0
- package/dist/fiscal/transport/types.js +88 -0
- package/dist/fiscal/transport/types.js.map +1 -0
- package/dist/import/br-documents.d.ts +26 -0
- package/dist/import/br-documents.d.ts.map +1 -0
- package/dist/import/br-documents.js +78 -0
- package/dist/import/br-documents.js.map +1 -0
- package/dist/import/clients-import.d.ts +122 -4
- package/dist/import/clients-import.d.ts.map +1 -1
- package/dist/import/clients-import.js +341 -41
- package/dist/import/clients-import.js.map +1 -1
- package/dist/index.d.ts +145 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +120 -7
- package/dist/index.js.map +1 -1
- package/dist/legal/documents.d.ts +12 -1
- package/dist/legal/documents.d.ts.map +1 -1
- package/dist/legal/documents.js +162 -18
- package/dist/legal/documents.js.map +1 -1
- package/dist/legal/index.d.ts +2 -2
- package/dist/legal/index.d.ts.map +1 -1
- package/dist/legal/index.js +1 -1
- package/dist/legal/index.js.map +1 -1
- package/dist/legal/types.d.ts +114 -2
- package/dist/legal/types.d.ts.map +1 -1
- package/dist/legal/types.js.map +1 -1
- package/dist/onboarding/persistence.d.ts +10 -1
- package/dist/onboarding/persistence.d.ts.map +1 -1
- package/dist/onboarding/persistence.js +4 -4
- package/dist/onboarding/persistence.js.map +1 -1
- package/dist/pilot/go-live-checklist.d.ts +41 -0
- package/dist/pilot/go-live-checklist.d.ts.map +1 -0
- package/dist/pilot/go-live-checklist.js +209 -0
- package/dist/pilot/go-live-checklist.js.map +1 -0
- package/dist/pilot/milestone.d.ts +56 -0
- package/dist/pilot/milestone.d.ts.map +1 -0
- package/dist/pilot/milestone.js +74 -0
- package/dist/pilot/milestone.js.map +1 -0
- package/dist/platform/capabilities.d.ts +88 -0
- package/dist/platform/capabilities.d.ts.map +1 -0
- package/dist/platform/capabilities.js +169 -0
- package/dist/platform/capabilities.js.map +1 -0
- package/dist/platform/job-contract.d.ts +232 -0
- package/dist/platform/job-contract.d.ts.map +1 -0
- package/dist/platform/job-contract.js +403 -0
- package/dist/platform/job-contract.js.map +1 -0
- package/dist/rbac/catalog.d.ts.map +1 -1
- package/dist/rbac/catalog.js +110 -0
- package/dist/rbac/catalog.js.map +1 -1
- package/dist/subscription-billing/index.d.ts +8 -5
- package/dist/subscription-billing/index.d.ts.map +1 -1
- package/dist/subscription-billing/index.js +4 -3
- package/dist/subscription-billing/index.js.map +1 -1
- package/dist/subscription-billing/platform-exemption.d.ts +89 -0
- package/dist/subscription-billing/platform-exemption.d.ts.map +1 -0
- package/dist/subscription-billing/platform-exemption.js +113 -0
- package/dist/subscription-billing/platform-exemption.js.map +1 -0
- package/dist/subscription-billing/service.d.ts +74 -0
- package/dist/subscription-billing/service.d.ts.map +1 -1
- package/dist/subscription-billing/service.js +182 -16
- package/dist/subscription-billing/service.js.map +1 -1
- package/dist/tenancy/features.d.ts +69 -0
- package/dist/tenancy/features.d.ts.map +1 -0
- package/dist/tenancy/features.js +123 -0
- package/dist/tenancy/features.js.map +1 -0
- package/dist/tenancy/settings.d.ts +63 -0
- package/dist/tenancy/settings.d.ts.map +1 -0
- package/dist/tenancy/settings.js +218 -0
- package/dist/tenancy/settings.js.map +1 -0
- package/dist/users/repository.d.ts +16 -1
- package/dist/users/repository.d.ts.map +1 -1
- package/dist/users/repository.js +24 -1
- package/dist/users/repository.js.map +1 -1
- package/dist/vault/repository.d.ts +69 -1
- package/dist/vault/repository.d.ts.map +1 -1
- package/dist/vault/repository.js +88 -5
- package/dist/vault/repository.js.map +1 -1
- package/package.json +10 -2
- package/src/db/migrations/0045_role_write_scope.sql +122 -0
- package/src/db/migrations/0046_pilot_activation_model.sql +184 -0
- package/src/db/migrations/0047_recipient_clearance.sql +89 -0
- package/src/db/migrations/0048_item_type_note.sql +16 -0
- package/src/db/migrations/0049_national_fiscal_engine.sql +279 -0
- package/src/db/migrations/0050_fiscal_vocabulary_readonly.sql +29 -0
- package/src/db/migrations/0051_seed_rules_from_catalog.sql +72 -0
- package/src/db/migrations/0052_fiscal_rule_delete_scope.sql +57 -0
- package/src/db/migrations/0053_rule_validity_lower_bound.sql +44 -0
- package/src/db/migrations/0054_tenant_profile_and_rule_source.sql +89 -0
- package/src/db/migrations/0055_job_capability_contract.sql +300 -0
- package/src/db/migrations/0056_fiscal_document_ingestion.sql +337 -0
- package/src/db/migrations/0057_fiscal_pending_event_inbox.sql +228 -0
- package/src/db/migrations/0058_fiscal_operational_engine.sql +516 -0
- package/src/db/migrations/0059_fiscal_contract_version.sql +59 -0
- package/src/db/migrations/0060_fiscal_credential_vault_and_run_authorization.sql +321 -0
- package/src/db/migrations/0061_client_official_registry_provenance.sql +193 -0
- package/src/db/migrations/0062_first_contact_and_capability_truth.sql +119 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ensureSaasPlanCatalog = exports.getPlan = exports.listPublicPlans = void 0;
|
|
4
4
|
exports.seedSaasPlans = seedSaasPlans;
|
|
5
|
+
exports.provisionAccountingOffice = provisionAccountingOffice;
|
|
5
6
|
exports.signupSelfService = signupSelfService;
|
|
6
7
|
exports.standingFor = standingFor;
|
|
7
8
|
exports.entitlementsForPlan = entitlementsForPlan;
|
|
@@ -14,6 +15,7 @@ exports.reactivateForTenant = reactivateForTenant;
|
|
|
14
15
|
exports.backofficeListSubscriptions = backofficeListSubscriptions;
|
|
15
16
|
exports.backofficeOverview = backofficeOverview;
|
|
16
17
|
exports.backofficeListWebhookEvents = backofficeListWebhookEvents;
|
|
18
|
+
exports.backofficeSetPlatformBillingExemption = backofficeSetPlatformBillingExemption;
|
|
17
19
|
exports.backofficeActivateSubscription = backofficeActivateSubscription;
|
|
18
20
|
exports.retryFailedWebhookEvents = retryFailedWebhookEvents;
|
|
19
21
|
exports.runBillingCron = runBillingCron;
|
|
@@ -21,18 +23,20 @@ const shared_1 = require("@baruk/shared");
|
|
|
21
23
|
const context_js_1 = require("../db/context.js");
|
|
22
24
|
const audit_js_1 = require("../audit/audit.js");
|
|
23
25
|
const password_js_1 = require("../auth/password.js");
|
|
26
|
+
const repository_js_1 = require("../users/repository.js");
|
|
24
27
|
const provisioning_js_1 = require("../tenancy/provisioning.js");
|
|
25
|
-
const
|
|
28
|
+
const repository_js_2 = require("../products/repository.js");
|
|
26
29
|
const derive_js_1 = require("../entitlements/derive.js");
|
|
27
30
|
const transactional_outbound_js_1 = require("../mail/transactional-outbound.js");
|
|
28
31
|
const reconcile_js_1 = require("./reconcile.js");
|
|
32
|
+
const platform_exemption_js_1 = require("./platform-exemption.js");
|
|
29
33
|
const dunning_js_1 = require("./dunning.js");
|
|
30
34
|
const live_guard_js_1 = require("../billing/live-guard.js");
|
|
31
35
|
const registry_js_1 = require("./provider/registry.js");
|
|
32
|
-
const
|
|
33
|
-
Object.defineProperty(exports, "ensureSaasPlanCatalog", { enumerable: true, get: function () { return
|
|
34
|
-
Object.defineProperty(exports, "getPlan", { enumerable: true, get: function () { return
|
|
35
|
-
Object.defineProperty(exports, "listPublicPlans", { enumerable: true, get: function () { return
|
|
36
|
+
const repository_js_3 = require("./repository.js");
|
|
37
|
+
Object.defineProperty(exports, "ensureSaasPlanCatalog", { enumerable: true, get: function () { return repository_js_3.ensureSaasPlanCatalog; } });
|
|
38
|
+
Object.defineProperty(exports, "getPlan", { enumerable: true, get: function () { return repository_js_3.getPlan; } });
|
|
39
|
+
Object.defineProperty(exports, "listPublicPlans", { enumerable: true, get: function () { return repository_js_3.listPublicPlans; } });
|
|
36
40
|
const plans_js_1 = require("./plans.js");
|
|
37
41
|
const product_config_js_1 = require("./product-config.js");
|
|
38
42
|
function asRegistry(source) {
|
|
@@ -87,8 +91,70 @@ async function syncTenantStatus(tx, tenantId, status) {
|
|
|
87
91
|
}
|
|
88
92
|
/** Seed do catálogo padrão (chamado pelo seed do core). */
|
|
89
93
|
async function seedSaasPlans(db) {
|
|
90
|
-
await (0,
|
|
91
|
-
await (0,
|
|
94
|
+
await (0, repository_js_2.ensureProductCatalog)(db);
|
|
95
|
+
await (0, repository_js_3.ensureSaasPlanCatalog)(db, plans_js_1.SAAS_PLANS);
|
|
96
|
+
}
|
|
97
|
+
async function provisionAccountingOffice(db, input, nowIso) {
|
|
98
|
+
const email = input.ownerEmail.trim().toLowerCase();
|
|
99
|
+
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email))
|
|
100
|
+
throw new shared_1.ValidationError('E-mail inválido');
|
|
101
|
+
if (!input.companyName.trim())
|
|
102
|
+
throw new shared_1.ValidationError('Nome do escritório é obrigatório');
|
|
103
|
+
if (!input.ownerFullName.trim())
|
|
104
|
+
throw new shared_1.ValidationError('Nome do responsável é obrigatório');
|
|
105
|
+
const planKey = input.planKey ?? plans_js_1.SAAS_PLANS.find((p) => p.isActive && p.isPublic)?.key;
|
|
106
|
+
if (!planKey)
|
|
107
|
+
throw new shared_1.ValidationError('Nenhum plano ativo disponível');
|
|
108
|
+
const plan = await (0, repository_js_3.getPlan)(db, planKey);
|
|
109
|
+
if (!plan || !plan.isActive)
|
|
110
|
+
throw new shared_1.ValidationError(`Plano indisponível: ${planKey}`);
|
|
111
|
+
const code = await uniqueTenantCode(db, input.companyName);
|
|
112
|
+
const tenantId = await (0, provisioning_js_1.ensureTenant)(db, {
|
|
113
|
+
code,
|
|
114
|
+
displayName: input.companyName.trim(),
|
|
115
|
+
status: 'trial',
|
|
116
|
+
primaryProduct: plans_js_1.DEFAULT_PRODUCT_KEY,
|
|
117
|
+
});
|
|
118
|
+
await (0, provisioning_js_1.ensureOrganization)(db, tenantId, input.companyName.trim());
|
|
119
|
+
await (0, repository_js_2.ensureProductCatalog)(db);
|
|
120
|
+
await (0, repository_js_2.ensureTenantProduct)(db, tenantId, plans_js_1.DEFAULT_PRODUCT_KEY);
|
|
121
|
+
const trialEndsAt = addDays(nowIso, plan.trialDays > 0 ? plan.trialDays : plans_js_1.DEFAULT_TRIAL_DAYS);
|
|
122
|
+
const { subscription, domainEvents } = (0, reconcile_js_1.startTrial)(tenantId, plan.key, trialEndsAt, nowIso);
|
|
123
|
+
/*
|
|
124
|
+
* Contexto do TENANT NOVO com o usuário da OPERADORA.
|
|
125
|
+
*
|
|
126
|
+
* O operador não é membro deste escritório e nunca será — ele abre o contexto
|
|
127
|
+
* para criar o convite e sai. O `invited_by` aponta para ele, que é a
|
|
128
|
+
* resposta honesta a "quem colocou esta pessoa aqui".
|
|
129
|
+
*/
|
|
130
|
+
return (0, context_js_1.withContext)(db, { tenantId, userId: input.operatorUserId }, async (tx) => {
|
|
131
|
+
const invited = await (0, repository_js_1.inviteUser)(tx, {
|
|
132
|
+
email,
|
|
133
|
+
fullName: input.ownerFullName.trim(),
|
|
134
|
+
roleKey: 'owner',
|
|
135
|
+
invitedBy: input.operatorUserId,
|
|
136
|
+
});
|
|
137
|
+
const row = await (0, repository_js_3.upsertSubscription)(tx, { tenantId, planKey: plan.key, subscription });
|
|
138
|
+
await (0, repository_js_3.appendDomainEvents)(tx, row.rowId, domainEvents);
|
|
139
|
+
await (0, audit_js_1.appendAudit)(tx, {
|
|
140
|
+
actorId: input.operatorUserId,
|
|
141
|
+
action: 'tenant.provisioned_by_operator',
|
|
142
|
+
resourceType: 'tenant',
|
|
143
|
+
resourceId: tenantId,
|
|
144
|
+
metadata: { planKey: plan.key, trialEndsAt, tenantCode: code, ownerEmail: email },
|
|
145
|
+
ip: input.ip ?? null,
|
|
146
|
+
userAgent: input.userAgent ?? null,
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
tenantId,
|
|
150
|
+
tenantCode: code,
|
|
151
|
+
ownerUserId: invited.userId,
|
|
152
|
+
ownerEmail: invited.email,
|
|
153
|
+
planKey: plan.key,
|
|
154
|
+
trialEndsAt,
|
|
155
|
+
activationToken: invited.activationToken,
|
|
156
|
+
};
|
|
157
|
+
});
|
|
92
158
|
}
|
|
93
159
|
function slugify(name) {
|
|
94
160
|
return name
|
|
@@ -99,6 +165,31 @@ function slugify(name) {
|
|
|
99
165
|
.replace(/^-+|-+$/g, '')
|
|
100
166
|
.slice(0, 40);
|
|
101
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Código do escritório a partir do nome, único na base.
|
|
170
|
+
*
|
|
171
|
+
* Extraído do signup quando o provisionamento pela operadora passou a precisar
|
|
172
|
+
* do mesmo cálculo. Duas cópias da regra de colisão renderiam dois códigos
|
|
173
|
+
* diferentes para o mesmo nome dependendo de por qual porta o escritório
|
|
174
|
+
* entrou — e o código aparece em referência de cobrança já emitida.
|
|
175
|
+
*/
|
|
176
|
+
async function uniqueTenantCode(db, companyName) {
|
|
177
|
+
const base = slugify(companyName) || 'escritorio';
|
|
178
|
+
let code = base;
|
|
179
|
+
for (let i = 2;; i += 1) {
|
|
180
|
+
const clash = await db `
|
|
181
|
+
SELECT id FROM tenant WHERE lower(code) = lower(${code}) AND deleted_at IS NULL
|
|
182
|
+
`;
|
|
183
|
+
if (!clash[0])
|
|
184
|
+
break;
|
|
185
|
+
code = `${base}-${i}`;
|
|
186
|
+
if (i > 50) {
|
|
187
|
+
code = `${base}-${(0, shared_1.uuidv7)().slice(-6)}`;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return code;
|
|
192
|
+
}
|
|
102
193
|
/**
|
|
103
194
|
* Cadastro self-service (Fase 17): cria usuário + tenant em TRIAL + organização +
|
|
104
195
|
* membership com papel `owner` + entitlement do produto + assinatura `trialing`.
|
|
@@ -112,7 +203,7 @@ async function signupSelfService(db, input, nowIso) {
|
|
|
112
203
|
throw new shared_1.ValidationError('Senha deve ter ao menos 8 caracteres');
|
|
113
204
|
if (!input.companyName.trim())
|
|
114
205
|
throw new shared_1.ValidationError('Nome da empresa é obrigatório');
|
|
115
|
-
const plan = await (0,
|
|
206
|
+
const plan = await (0, repository_js_3.getPlan)(db, input.planKey);
|
|
116
207
|
if (!plan || !plan.isActive || !plan.isPublic) {
|
|
117
208
|
throw new shared_1.ValidationError(`Plano indisponível: ${input.planKey}`);
|
|
118
209
|
}
|
|
@@ -123,20 +214,7 @@ async function signupSelfService(db, input, nowIso) {
|
|
|
123
214
|
throw new shared_1.ConflictError('Já existe uma conta com este e-mail. Faça login para continuar.');
|
|
124
215
|
}
|
|
125
216
|
// Código único do tenant a partir do nome (sufixo em caso de colisão).
|
|
126
|
-
const
|
|
127
|
-
let code = base;
|
|
128
|
-
for (let i = 2;; i += 1) {
|
|
129
|
-
const clash = await db `
|
|
130
|
-
SELECT id FROM tenant WHERE lower(code) = lower(${code}) AND deleted_at IS NULL
|
|
131
|
-
`;
|
|
132
|
-
if (!clash[0])
|
|
133
|
-
break;
|
|
134
|
-
code = `${base}-${i}`;
|
|
135
|
-
if (i > 50) {
|
|
136
|
-
code = `${base}-${(0, shared_1.uuidv7)().slice(-6)}`;
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
217
|
+
const code = await uniqueTenantCode(db, input.companyName);
|
|
140
218
|
// INSERT puro (não upsert): o papel de app pode CRIAR credencial, nunca
|
|
141
219
|
// sobrescrever (REVOKE UPDATE em user_credential — anti account-takeover).
|
|
142
220
|
// A checagem de e-mail acima já garante que o usuário é novo.
|
|
@@ -159,13 +237,13 @@ async function signupSelfService(db, input, nowIso) {
|
|
|
159
237
|
await (0, provisioning_js_1.ensureOrganization)(db, tenantId, input.companyName.trim());
|
|
160
238
|
await (0, provisioning_js_1.ensureMembership)(db, tenantId, user.id);
|
|
161
239
|
await (0, provisioning_js_1.assignSystemRole)(db, tenantId, user.id, 'owner');
|
|
162
|
-
await (0,
|
|
163
|
-
await (0,
|
|
240
|
+
await (0, repository_js_2.ensureProductCatalog)(db);
|
|
241
|
+
await (0, repository_js_2.ensureTenantProduct)(db, tenantId, 'contabil');
|
|
164
242
|
const trialEndsAt = addDays(nowIso, plan.trialDays > 0 ? plan.trialDays : 14);
|
|
165
243
|
const { subscription, domainEvents } = (0, reconcile_js_1.startTrial)(tenantId, plan.key, trialEndsAt, nowIso);
|
|
166
244
|
await (0, context_js_1.withContext)(db, { tenantId, userId: user.id }, async (tx) => {
|
|
167
|
-
const row = await (0,
|
|
168
|
-
await (0,
|
|
245
|
+
const row = await (0, repository_js_3.upsertSubscription)(tx, { tenantId, planKey: plan.key, subscription });
|
|
246
|
+
await (0, repository_js_3.appendDomainEvents)(tx, row.rowId, domainEvents);
|
|
169
247
|
await (0, audit_js_1.appendAudit)(tx, {
|
|
170
248
|
actorId: user.id,
|
|
171
249
|
action: 'signup',
|
|
@@ -211,17 +289,18 @@ function entitlementsForPlan(sub, plan, nowIso) {
|
|
|
211
289
|
});
|
|
212
290
|
}
|
|
213
291
|
async function subscriptionOverview(db, ctx, nowIso) {
|
|
214
|
-
const { sub, invoices, events } = await (0, context_js_1.withContext)(db, ctx, async (tx) => {
|
|
215
|
-
const sub0 = await (0,
|
|
292
|
+
const { sub, invoices, events, platformBilling } = await (0, context_js_1.withContext)(db, ctx, async (tx) => {
|
|
293
|
+
const sub0 = await (0, repository_js_3.getSubscription)(tx);
|
|
216
294
|
return {
|
|
217
295
|
sub: sub0,
|
|
218
|
-
invoices: sub0 ? await (0,
|
|
219
|
-
events: sub0 ? await (0,
|
|
296
|
+
invoices: sub0 ? await (0, repository_js_3.listInvoices)(tx) : [],
|
|
297
|
+
events: sub0 ? await (0, repository_js_3.listBillingEvents)(tx, 20) : [],
|
|
298
|
+
platformBilling: await (0, platform_exemption_js_1.readTenantPlatformBilling)(tx, ctx.tenantId),
|
|
220
299
|
};
|
|
221
300
|
});
|
|
222
301
|
// Fora da transação: getPlan usa outra conexão do pool — dentro dela seria
|
|
223
302
|
// um segundo checkout de conexão com transação aberta (deadlock de pool).
|
|
224
|
-
const plan = sub ? await (0,
|
|
303
|
+
const plan = sub ? await (0, repository_js_3.getPlan)(db, sub.planKey) : null;
|
|
225
304
|
return {
|
|
226
305
|
subscription: sub,
|
|
227
306
|
plan,
|
|
@@ -229,6 +308,8 @@ async function subscriptionOverview(db, ctx, nowIso) {
|
|
|
229
308
|
invoices,
|
|
230
309
|
entitlements: entitlementsForPlan(sub, plan, nowIso),
|
|
231
310
|
events,
|
|
311
|
+
platformBilling,
|
|
312
|
+
platformBillingExempt: (0, platform_exemption_js_1.isPlatformBillingExempt)(platformBilling),
|
|
232
313
|
};
|
|
233
314
|
}
|
|
234
315
|
/**
|
|
@@ -238,7 +319,7 @@ async function subscriptionOverview(db, ctx, nowIso) {
|
|
|
238
319
|
* manual (backoffice) — nunca cobra por falta de configuração.
|
|
239
320
|
*/
|
|
240
321
|
async function startCheckout(db, ctx, source, planKey, _nowIso, productKey = plans_js_1.DEFAULT_PRODUCT_KEY) {
|
|
241
|
-
const plan = await (0,
|
|
322
|
+
const plan = await (0, repository_js_3.getPlan)(db, planKey, productKey);
|
|
242
323
|
if (!plan || !plan.isActive || !plan.isPublic) {
|
|
243
324
|
throw new shared_1.ValidationError(`Plano indisponível: ${planKey}`);
|
|
244
325
|
}
|
|
@@ -250,6 +331,21 @@ async function startCheckout(db, ctx, source, planKey, _nowIso, productKey = pla
|
|
|
250
331
|
// A conta de gateway e a URL de retorno saem do PRODUTO do plano — nunca de
|
|
251
332
|
// uma configuração global. É isso que impede o checkout de um produto voltar
|
|
252
333
|
// para o domínio de outro, ou cobrar na conta errada.
|
|
334
|
+
// ═══ O portão da isenção vem ANTES do gateway ═════════════════════════════
|
|
335
|
+
//
|
|
336
|
+
// Um tenant isento da assinatura da plataforma não deve nem chegar a existir
|
|
337
|
+
// como cliente no gateway: `ensureCustomer` cria cadastro, `createCheckout`
|
|
338
|
+
// cria link de cobrança, e um link emitido é uma cobrança que alguém pode
|
|
339
|
+
// pagar. Recusar depois — ao reconciliar o webhook — já teria custado dinheiro
|
|
340
|
+
// ao escritório fundador.
|
|
341
|
+
//
|
|
342
|
+
// A isenção NÃO desliga o financeiro do escritório: `receivable`, honorários e
|
|
343
|
+
// régua continuam intactos. O que ela desliga é a cobrança que a Baruk faz ao
|
|
344
|
+
// escritório, e só ela.
|
|
345
|
+
const billing = await (0, context_js_1.withContext)(db, ctx, (tx) => (0, platform_exemption_js_1.readTenantPlatformBilling)(tx, ctx.tenantId));
|
|
346
|
+
if ((0, platform_exemption_js_1.isPlatformBillingExempt)(billing)) {
|
|
347
|
+
throw new platform_exemption_js_1.PlatformBillingExemptError(billing.exemptionReason);
|
|
348
|
+
}
|
|
253
349
|
const cfg = asRegistry(source).resolve({ productKey: plan.productKey, tenantId: ctx.tenantId });
|
|
254
350
|
const provider = providerFor(cfg);
|
|
255
351
|
if (provider.mode === 'disabled') {
|
|
@@ -270,7 +366,7 @@ async function startCheckout(db, ctx, source, planKey, _nowIso, productKey = pla
|
|
|
270
366
|
const userRows = await tx `
|
|
271
367
|
SELECT email FROM "user" WHERE id = ${ctx.userId}
|
|
272
368
|
`;
|
|
273
|
-
const sub = await (0,
|
|
369
|
+
const sub = await (0, repository_js_3.getSubscription)(tx);
|
|
274
370
|
return {
|
|
275
371
|
tenantName: tenantRows[0]?.display_name ?? 'Tenant Baruk',
|
|
276
372
|
email: userRows[0]?.email ?? null,
|
|
@@ -297,8 +393,8 @@ async function startCheckout(db, ctx, source, planKey, _nowIso, productKey = pla
|
|
|
297
393
|
// 3) Persistência curta: SOMENTE as referências de provider (nunca o estado
|
|
298
394
|
// da assinatura — um webhook pode tê-la mudado durante a chamada de rede).
|
|
299
395
|
await (0, context_js_1.withContext)(db, ctx, async (tx) => {
|
|
300
|
-
await (0,
|
|
301
|
-
await (0,
|
|
396
|
+
await (0, repository_js_3.lockTenantBilling)(tx, ctx.tenantId);
|
|
397
|
+
await (0, repository_js_3.setSubscriptionProviderRefs)(tx, ctx.tenantId, provider.name, customer.externalId);
|
|
302
398
|
await (0, audit_js_1.appendAudit)(tx, {
|
|
303
399
|
actorId: ctx.userId,
|
|
304
400
|
action: 'checkout_started',
|
|
@@ -355,7 +451,7 @@ async function processWebhook(db, source, headers, rawBody, payload, nowIso, pro
|
|
|
355
451
|
const event = provider.parseWebhookEvent(payload);
|
|
356
452
|
if (!event)
|
|
357
453
|
return { outcome: 'ignored' };
|
|
358
|
-
const webhookId = await (0,
|
|
454
|
+
const webhookId = await (0, repository_js_3.insertWebhookEvent)(db, {
|
|
359
455
|
provider: provider.name,
|
|
360
456
|
externalEventId: event.externalEventId,
|
|
361
457
|
eventType: event.eventType,
|
|
@@ -372,7 +468,7 @@ async function processWebhook(db, source, headers, rawBody, payload, nowIso, pro
|
|
|
372
468
|
async function reconcileStoredWebhookEvent(db, provider, event, webhookId, nowIso, expectedProductKey = plans_js_1.DEFAULT_PRODUCT_KEY) {
|
|
373
469
|
const attribution = parseAttribution(event);
|
|
374
470
|
if (!attribution) {
|
|
375
|
-
await (0,
|
|
471
|
+
await (0, repository_js_3.markWebhookEvent)(db, webhookId, 'ignored', null, 'externalReference ausente/inválida');
|
|
376
472
|
return { outcome: 'ignored' };
|
|
377
473
|
}
|
|
378
474
|
// ISOLAMENTO FINANCEIRO: a conta que assinou o webhook é a conta de UM
|
|
@@ -380,15 +476,15 @@ async function reconcileStoredWebhookEvent(db, provider, event, webhookId, nowIs
|
|
|
380
476
|
// errada no gateway — ou é tentativa de mover dinheiro entre produtos.
|
|
381
477
|
// Recusar é obrigatório: reconciliar aqui escreveria na assinatura errada.
|
|
382
478
|
if (attribution.productKey !== expectedProductKey) {
|
|
383
|
-
await (0,
|
|
479
|
+
await (0, repository_js_3.markWebhookEvent)(db, webhookId, 'ignored', null, `produto divergente: evento=${attribution.productKey} conta=${expectedProductKey}`);
|
|
384
480
|
return { outcome: 'ignored' };
|
|
385
481
|
}
|
|
386
482
|
try {
|
|
387
|
-
const plan = await (0,
|
|
483
|
+
const plan = await (0, repository_js_3.getPlan)(db, attribution.planKey, attribution.productKey);
|
|
388
484
|
const { tenantId } = attribution;
|
|
389
485
|
const applied = await (0, context_js_1.withContext)(db, { tenantId }, async (tx) => {
|
|
390
|
-
await (0,
|
|
391
|
-
const current = await (0,
|
|
486
|
+
await (0, repository_js_3.lockTenantBilling)(tx, tenantId);
|
|
487
|
+
const current = await (0, repository_js_3.getSubscription)(tx);
|
|
392
488
|
// Guarda de ordenação (webhook atrasado): um OVERDUE que chega DEPOIS do
|
|
393
489
|
// pagamento do mesmo ciclo (período corrente ainda vigente) é obsoleto —
|
|
394
490
|
// aplicá-lo marcaria past_due uma assinatura em dia. Política de
|
|
@@ -448,7 +544,7 @@ async function reconcileStoredWebhookEvent(db, provider, event, webhookId, nowIs
|
|
|
448
544
|
currentPeriodEnd: addMonths(nowIso, plan.periodicity === 'yearly' ? 12 : 3),
|
|
449
545
|
};
|
|
450
546
|
}
|
|
451
|
-
const row = await (0,
|
|
547
|
+
const row = await (0, repository_js_3.upsertSubscription)(tx, {
|
|
452
548
|
tenantId,
|
|
453
549
|
planKey: effectivePlanKey ?? current?.planKey ?? next.items[0]?.planKey ?? 'starter',
|
|
454
550
|
subscription: next,
|
|
@@ -456,9 +552,9 @@ async function reconcileStoredWebhookEvent(db, provider, event, webhookId, nowIs
|
|
|
456
552
|
providerCustomerId: event.externalCustomerId ?? null,
|
|
457
553
|
providerSubscriptionId: event.subscription?.externalId ?? null,
|
|
458
554
|
});
|
|
459
|
-
await (0,
|
|
555
|
+
await (0, repository_js_3.appendDomainEvents)(tx, row.rowId, domainEvents);
|
|
460
556
|
if (event.invoice) {
|
|
461
|
-
await (0,
|
|
557
|
+
await (0, repository_js_3.upsertInvoice)(tx, {
|
|
462
558
|
tenantId,
|
|
463
559
|
subscriptionRowId: row.rowId,
|
|
464
560
|
provider: provider.name,
|
|
@@ -486,25 +582,25 @@ async function reconcileStoredWebhookEvent(db, provider, event, webhookId, nowIs
|
|
|
486
582
|
return null;
|
|
487
583
|
});
|
|
488
584
|
if (applied !== null) {
|
|
489
|
-
await (0,
|
|
585
|
+
await (0, repository_js_3.markWebhookEvent)(db, webhookId, 'ignored', attribution.tenantId, applied);
|
|
490
586
|
return { outcome: 'ignored', tenantId: attribution.tenantId };
|
|
491
587
|
}
|
|
492
|
-
await (0,
|
|
588
|
+
await (0, repository_js_3.markWebhookEvent)(db, webhookId, 'processed', attribution.tenantId);
|
|
493
589
|
return { outcome: 'processed', tenantId: attribution.tenantId };
|
|
494
590
|
}
|
|
495
591
|
catch (err) {
|
|
496
|
-
await (0,
|
|
592
|
+
await (0, repository_js_3.markWebhookEvent)(db, webhookId, 'failed', attribution.tenantId, err instanceof Error ? err.message : String(err));
|
|
497
593
|
return { outcome: 'failed', tenantId: attribution.tenantId };
|
|
498
594
|
}
|
|
499
595
|
}
|
|
500
596
|
// ── Gestão da assinatura (tenant) ────────────────────────────────────────────
|
|
501
597
|
async function changePlanForTenant(db, ctx, newPlanKey, nowIso) {
|
|
502
|
-
const plan = await (0,
|
|
598
|
+
const plan = await (0, repository_js_3.getPlan)(db, newPlanKey);
|
|
503
599
|
if (!plan || !plan.isActive)
|
|
504
600
|
throw new shared_1.ValidationError(`Plano desconhecido: ${newPlanKey}`);
|
|
505
601
|
return (0, context_js_1.withContext)(db, ctx, async (tx) => {
|
|
506
|
-
await (0,
|
|
507
|
-
const current = await (0,
|
|
602
|
+
await (0, repository_js_3.lockTenantBilling)(tx, ctx.tenantId);
|
|
603
|
+
const current = await (0, repository_js_3.getSubscription)(tx);
|
|
508
604
|
if (!current)
|
|
509
605
|
throw new shared_1.NotFoundError('Nenhuma assinatura para este tenant');
|
|
510
606
|
if (current.status === 'canceled') {
|
|
@@ -513,12 +609,12 @@ async function changePlanForTenant(db, ctx, newPlanKey, nowIso) {
|
|
|
513
609
|
if (current.planKey === plan.key)
|
|
514
610
|
return current;
|
|
515
611
|
const { subscription, domainEvents } = (0, reconcile_js_1.changePlan)(current, plan.key, nowIso);
|
|
516
|
-
const row = await (0,
|
|
612
|
+
const row = await (0, repository_js_3.upsertSubscription)(tx, {
|
|
517
613
|
tenantId: ctx.tenantId,
|
|
518
614
|
planKey: plan.key,
|
|
519
615
|
subscription,
|
|
520
616
|
});
|
|
521
|
-
await (0,
|
|
617
|
+
await (0, repository_js_3.appendDomainEvents)(tx, row.rowId, domainEvents);
|
|
522
618
|
await (0, audit_js_1.appendAudit)(tx, {
|
|
523
619
|
actorId: ctx.userId,
|
|
524
620
|
action: 'plan_changed',
|
|
@@ -547,7 +643,7 @@ async function changePlanForTenant(db, ctx, newPlanKey, nowIso) {
|
|
|
547
643
|
*/
|
|
548
644
|
async function cancelForTenant(db, ctx, source, nowIso, productKey = plans_js_1.DEFAULT_PRODUCT_KEY) {
|
|
549
645
|
// Fora da transação: chamada de rede não pode segurar o lock do tenant.
|
|
550
|
-
const existing = await (0, context_js_1.withContext)(db, ctx, (tx) => (0,
|
|
646
|
+
const existing = await (0, context_js_1.withContext)(db, ctx, (tx) => (0, repository_js_3.getSubscription)(tx, productKey));
|
|
551
647
|
if (!existing)
|
|
552
648
|
throw new shared_1.NotFoundError('Nenhuma assinatura para este tenant');
|
|
553
649
|
let providerOutcome = 'skipped_no_provider_id';
|
|
@@ -563,8 +659,8 @@ async function cancelForTenant(db, ctx, source, nowIso, productKey = plans_js_1.
|
|
|
563
659
|
}
|
|
564
660
|
}
|
|
565
661
|
return (0, context_js_1.withContext)(db, ctx, async (tx) => {
|
|
566
|
-
await (0,
|
|
567
|
-
const current = await (0,
|
|
662
|
+
await (0, repository_js_3.lockTenantBilling)(tx, ctx.tenantId);
|
|
663
|
+
const current = await (0, repository_js_3.getSubscription)(tx, productKey);
|
|
568
664
|
if (!current)
|
|
569
665
|
throw new shared_1.NotFoundError('Nenhuma assinatura para este tenant');
|
|
570
666
|
// Idempotência: cancelar o que já está cancelado devolve o estado, sem erro
|
|
@@ -572,12 +668,12 @@ async function cancelForTenant(db, ctx, source, nowIso, productKey = plans_js_1.
|
|
|
572
668
|
if (current.status === 'canceled')
|
|
573
669
|
return current;
|
|
574
670
|
const { subscription, domainEvents } = (0, reconcile_js_1.cancelSubscription)(current, nowIso);
|
|
575
|
-
const row = await (0,
|
|
671
|
+
const row = await (0, repository_js_3.upsertSubscription)(tx, {
|
|
576
672
|
tenantId: ctx.tenantId,
|
|
577
673
|
planKey: current.planKey,
|
|
578
674
|
subscription,
|
|
579
675
|
});
|
|
580
|
-
await (0,
|
|
676
|
+
await (0, repository_js_3.appendDomainEvents)(tx, row.rowId, domainEvents);
|
|
581
677
|
await syncTenantStatus(tx, ctx.tenantId, subscription.status);
|
|
582
678
|
await (0, audit_js_1.appendAudit)(tx, {
|
|
583
679
|
actorId: ctx.userId,
|
|
@@ -597,7 +693,7 @@ async function cancelForTenant(db, ctx, source, nowIso, productKey = plans_js_1.
|
|
|
597
693
|
* devolve o checkout; em modo 'disabled' a reativação é manual (backoffice).
|
|
598
694
|
*/
|
|
599
695
|
async function reactivateForTenant(db, ctx, source, nowIso, productKey = plans_js_1.DEFAULT_PRODUCT_KEY) {
|
|
600
|
-
const sub = await (0, context_js_1.withContext)(db, ctx, (tx) => (0,
|
|
696
|
+
const sub = await (0, context_js_1.withContext)(db, ctx, (tx) => (0, repository_js_3.getSubscription)(tx, productKey));
|
|
601
697
|
if (!sub)
|
|
602
698
|
throw new shared_1.NotFoundError('Nenhuma assinatura para este tenant');
|
|
603
699
|
if (sub.status === 'active' || sub.status === 'trialing') {
|
|
@@ -607,10 +703,10 @@ async function reactivateForTenant(db, ctx, source, nowIso, productKey = plans_j
|
|
|
607
703
|
}
|
|
608
704
|
// ── Backoffice (operadora) ───────────────────────────────────────────────────
|
|
609
705
|
async function backofficeListSubscriptions(db, filter = {}) {
|
|
610
|
-
return (0,
|
|
706
|
+
return (0, repository_js_3.withOperatorContext)(db, (tx) => (0, repository_js_3.listAllSubscriptions)(tx, filter));
|
|
611
707
|
}
|
|
612
708
|
async function backofficeOverview(db) {
|
|
613
|
-
return (0,
|
|
709
|
+
return (0, repository_js_3.withOperatorContext)(db, (tx) => (0, repository_js_3.backofficeSummary)(tx));
|
|
614
710
|
}
|
|
615
711
|
async function backofficeListWebhookEvents(db, limit = 100) {
|
|
616
712
|
const rows = await db `
|
|
@@ -634,13 +730,85 @@ async function backofficeListWebhookEvents(db, limit = 100) {
|
|
|
634
730
|
* simula uma fatura `received` e reconcilia pelo MESMO caminho do webhook —
|
|
635
731
|
* nenhuma transição de estado fora do domínio puro.
|
|
636
732
|
*/
|
|
733
|
+
/**
|
|
734
|
+
* A operadora declara — ou revoga — a isenção da assinatura de plataforma.
|
|
735
|
+
*
|
|
736
|
+
* ## Por que esta função existe, e por que ela não existia
|
|
737
|
+
*
|
|
738
|
+
* A C1 entregou `tenant_platform_billing` com RLS por comando e testes verdes, e
|
|
739
|
+
* a tabela terminou o deploy com ZERO linhas. Não por esquecimento: não havia
|
|
740
|
+
* caminho de produto para escrevê-la. `setTenantPlatformBilling` era exportada e
|
|
741
|
+
* alcançável só por código, o que na prática significa "alguém abre um console e
|
|
742
|
+
* roda um script" — exatamente o tipo de ato que a tabela existe para tornar
|
|
743
|
+
* auditável.
|
|
744
|
+
*
|
|
745
|
+
* Um mecanismo cujo único acionamento é um script fora do produto não é um
|
|
746
|
+
* mecanismo auditável; é um mecanismo com a auditoria de fora.
|
|
747
|
+
*
|
|
748
|
+
* ## Quem pode
|
|
749
|
+
*
|
|
750
|
+
* Só a OPERADORA (allowlist de e-mails do backoffice). O tenant não escreve a
|
|
751
|
+
* própria isenção — a RLS da 0060 já garante isso, e esta rota não é uma segunda
|
|
752
|
+
* barreira, é o caminho que atravessa a primeira legitimamente, com
|
|
753
|
+
* `withOperatorContext`.
|
|
754
|
+
*
|
|
755
|
+
* ## O que fica gravado
|
|
756
|
+
*
|
|
757
|
+
* `granted_by` é o USUÁRIO operador, não um rótulo. `granted_at` sai do banco.
|
|
758
|
+
* E a trilha registra o e-mail de quem decidiu, o motivo e o tenant — porque a
|
|
759
|
+
* pergunta que alguém vai fazer daqui a um ano é "quem isentou este escritório,
|
|
760
|
+
* quando e por quê", e ela não pode depender de memória.
|
|
761
|
+
*
|
|
762
|
+
* Revogar usa a mesma porta: `billingMode: 'standard'` limpa motivo e data, e o
|
|
763
|
+
* motor volta a cobrar. Uma isenção que só se concede é uma isenção permanente
|
|
764
|
+
* por acidente.
|
|
765
|
+
*/
|
|
766
|
+
async function backofficeSetPlatformBillingExemption(db, operator, input) {
|
|
767
|
+
const tenants = await db `
|
|
768
|
+
SELECT id FROM tenant WHERE id = ${input.tenantId} AND deleted_at IS NULL
|
|
769
|
+
`;
|
|
770
|
+
if (!tenants[0])
|
|
771
|
+
throw new shared_1.ValidationError(`Tenant desconhecido: ${input.tenantId}`);
|
|
772
|
+
const record = await (0, repository_js_3.withOperatorContext)(db, (tx) => (0, platform_exemption_js_1.setTenantPlatformBilling)(tx, {
|
|
773
|
+
tenantId: input.tenantId,
|
|
774
|
+
billingMode: input.billingMode,
|
|
775
|
+
exemptionReason: input.exemptionReason ?? null,
|
|
776
|
+
foundingTenant: input.foundingTenant ?? false,
|
|
777
|
+
grantedBy: operator.userId,
|
|
778
|
+
expiresOn: input.expiresOn ?? null,
|
|
779
|
+
notes: input.notes ?? null,
|
|
780
|
+
}));
|
|
781
|
+
/*
|
|
782
|
+
* A trilha é escrita no contexto do TENANT afetado, e não no do operador: é lá
|
|
783
|
+
* que alguém vai procurar por que aquele escritório não é cobrado. `audit_log`
|
|
784
|
+
* é tenant-scoped, e gravar no lugar errado é o mesmo que não gravar.
|
|
785
|
+
*/
|
|
786
|
+
await (0, context_js_1.withContext)(db, { tenantId: input.tenantId, userId: operator.userId }, (tx) => (0, audit_js_1.appendAudit)(tx, {
|
|
787
|
+
actorType: 'user',
|
|
788
|
+
actorId: operator.userId,
|
|
789
|
+
action: record.billingMode === 'exempt'
|
|
790
|
+
? 'platform_billing_exemption_granted'
|
|
791
|
+
: 'platform_billing_exemption_revoked',
|
|
792
|
+
resourceType: 'tenant_platform_billing',
|
|
793
|
+
resourceId: null,
|
|
794
|
+
metadata: {
|
|
795
|
+
operatorEmail: operator.email,
|
|
796
|
+
billingMode: record.billingMode,
|
|
797
|
+
exemptionReason: record.exemptionReason,
|
|
798
|
+
foundingTenant: record.foundingTenant,
|
|
799
|
+
expiresOn: record.expiresOn,
|
|
800
|
+
notes: record.notes,
|
|
801
|
+
},
|
|
802
|
+
}));
|
|
803
|
+
return record;
|
|
804
|
+
}
|
|
637
805
|
async function backofficeActivateSubscription(db, operatorEmail, tenantId, planKey, nowIso) {
|
|
638
|
-
const plan = await (0,
|
|
806
|
+
const plan = await (0, repository_js_3.getPlan)(db, planKey);
|
|
639
807
|
if (!plan)
|
|
640
808
|
throw new shared_1.ValidationError(`Plano desconhecido: ${planKey}`);
|
|
641
809
|
return (0, context_js_1.withContext)(db, { tenantId }, async (tx) => {
|
|
642
|
-
await (0,
|
|
643
|
-
const current = await (0,
|
|
810
|
+
await (0, repository_js_3.lockTenantBilling)(tx, tenantId);
|
|
811
|
+
const current = await (0, repository_js_3.getSubscription)(tx);
|
|
644
812
|
const manualEvent = {
|
|
645
813
|
externalEventId: `manual_${(0, shared_1.uuidv7)()}`,
|
|
646
814
|
eventType: 'manual.activation',
|
|
@@ -661,14 +829,14 @@ async function backofficeActivateSubscription(db, operatorEmail, tenantId, planK
|
|
|
661
829
|
event: manualEvent,
|
|
662
830
|
now: nowIso,
|
|
663
831
|
});
|
|
664
|
-
const row = await (0,
|
|
832
|
+
const row = await (0, repository_js_3.upsertSubscription)(tx, {
|
|
665
833
|
tenantId,
|
|
666
834
|
planKey: plan.key,
|
|
667
835
|
subscription,
|
|
668
836
|
provider: 'manual',
|
|
669
837
|
});
|
|
670
|
-
await (0,
|
|
671
|
-
await (0,
|
|
838
|
+
await (0, repository_js_3.appendDomainEvents)(tx, row.rowId, domainEvents);
|
|
839
|
+
await (0, repository_js_3.upsertInvoice)(tx, {
|
|
672
840
|
tenantId,
|
|
673
841
|
subscriptionRowId: row.rowId,
|
|
674
842
|
provider: 'manual',
|
|
@@ -697,14 +865,14 @@ async function backofficeActivateSubscription(db, operatorEmail, tenantId, planK
|
|
|
697
865
|
async function retryFailedWebhookEvents(db, source, nowIso, limit = 25, productKey = plans_js_1.DEFAULT_PRODUCT_KEY) {
|
|
698
866
|
const cfg = asRegistry(source).resolve({ productKey });
|
|
699
867
|
const provider = providerFor(cfg);
|
|
700
|
-
const failed = await (0,
|
|
868
|
+
const failed = await (0, repository_js_3.listFailedWebhookEvents)(db, limit);
|
|
701
869
|
let recovered = 0;
|
|
702
870
|
for (const row of failed) {
|
|
703
871
|
if (row.provider !== provider.name)
|
|
704
872
|
continue;
|
|
705
873
|
const event = provider.parseWebhookEvent(row.payload);
|
|
706
874
|
if (!event) {
|
|
707
|
-
await (0,
|
|
875
|
+
await (0, repository_js_3.markWebhookEvent)(db, row.id, 'ignored', null, 'payload não parseável no reprocessamento');
|
|
708
876
|
continue;
|
|
709
877
|
}
|
|
710
878
|
const result = await reconcileStoredWebhookEvent(db, provider, event, row.id, nowIso, productKey);
|
|
@@ -748,7 +916,7 @@ async function runBillingCron(db, source, nowIso) {
|
|
|
748
916
|
report.webhooksRetried += retry.retried;
|
|
749
917
|
report.webhooksRecovered += retry.recovered;
|
|
750
918
|
}
|
|
751
|
-
const subs = await (0,
|
|
919
|
+
const subs = await (0, repository_js_3.withOperatorContext)(db, (tx) => (0, repository_js_3.listSubscriptionsForCron)(tx, today));
|
|
752
920
|
report.examined = subs.length;
|
|
753
921
|
for (const sub of subs) {
|
|
754
922
|
// Isolamento de falha: um tenant quebrado não pode derrubar a régua dos demais.
|
|
@@ -758,8 +926,8 @@ async function runBillingCron(db, source, nowIso) {
|
|
|
758
926
|
// assinatura — nunca de uma configuração global compartilhada.
|
|
759
927
|
const cfg = registry.resolve({ productKey: sub.productKey, tenantId: sub.tenantId });
|
|
760
928
|
await (0, context_js_1.withContext)(db, { tenantId: sub.tenantId }, async (tx) => {
|
|
761
|
-
await (0,
|
|
762
|
-
const loaded = await (0,
|
|
929
|
+
await (0, repository_js_3.lockTenantBilling)(tx, sub.tenantId);
|
|
930
|
+
const loaded = await (0, repository_js_3.getSubscription)(tx, sub.productKey);
|
|
763
931
|
if (!loaded)
|
|
764
932
|
return; // sumiu entre o scan e o lock (ex.: tenant removido)
|
|
765
933
|
let current = loaded;
|
|
@@ -801,30 +969,30 @@ async function runBillingCron(db, source, nowIso) {
|
|
|
801
969
|
...subscription,
|
|
802
970
|
currentPeriodEnd: subscription.currentPeriodEnd ?? reference,
|
|
803
971
|
};
|
|
804
|
-
const row = await (0,
|
|
972
|
+
const row = await (0, repository_js_3.upsertSubscription)(tx, {
|
|
805
973
|
tenantId: current.tenantId,
|
|
806
974
|
planKey: current.planKey,
|
|
807
975
|
subscription: next,
|
|
808
976
|
});
|
|
809
|
-
await (0,
|
|
977
|
+
await (0, repository_js_3.appendDomainEvents)(tx, row.rowId, domainEvents);
|
|
810
978
|
await (0, audit_js_1.appendAudit)(tx, {
|
|
811
979
|
actorType: 'automation',
|
|
812
980
|
action: trialExpired ? 'trial_expired' : 'period_expired',
|
|
813
981
|
resourceType: 'saas_subscription',
|
|
814
982
|
resourceId: row.rowId,
|
|
815
983
|
});
|
|
816
|
-
current = (await (0,
|
|
984
|
+
current = (await (0, repository_js_3.getSubscription)(tx));
|
|
817
985
|
}
|
|
818
986
|
}
|
|
819
987
|
// 2. Régua de inadimplência (idempotente por stepKey + reference_date).
|
|
820
988
|
if (current.status === 'past_due') {
|
|
821
989
|
const reference = current.currentPeriodEnd ?? current.trialEndsAt ?? today;
|
|
822
|
-
const executed = await (0,
|
|
990
|
+
const executed = await (0, repository_js_3.listExecutedDunningSteps)(tx, current.rowId, reference);
|
|
823
991
|
const events = (0, dunning_js_1.dunningStepsAsEvents)({ ...current, currentPeriodEnd: reference }, today, executed);
|
|
824
992
|
for (const ev of events) {
|
|
825
993
|
const stepKey = ev.data.dunningStep?.stepKey ??
|
|
826
994
|
`step_${ev.sequence}`;
|
|
827
|
-
await (0,
|
|
995
|
+
await (0, repository_js_3.recordDunningStep)(tx, {
|
|
828
996
|
tenantId: current.tenantId,
|
|
829
997
|
subscriptionRowId: current.rowId,
|
|
830
998
|
stepKey,
|
|
@@ -833,9 +1001,9 @@ async function runBillingCron(db, source, nowIso) {
|
|
|
833
1001
|
report.dunningStepsExecuted += 1;
|
|
834
1002
|
}
|
|
835
1003
|
if (events.length > 0) {
|
|
836
|
-
await (0,
|
|
1004
|
+
await (0, repository_js_3.appendDomainEvents)(tx, current.rowId, events);
|
|
837
1005
|
dunningEmailTo = await ownerEmailForTenant(tx, current.tenantId);
|
|
838
|
-
await (0,
|
|
1006
|
+
await (0, repository_js_3.upsertSubscription)(tx, {
|
|
839
1007
|
tenantId: current.tenantId,
|
|
840
1008
|
planKey: current.planKey,
|
|
841
1009
|
subscription: { ...current, sequence: current.sequence + events.length },
|