@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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { isRetryableProviderError, CANONICAL_PROVIDER_ERROR_MESSAGES, SUBSCRIPTION_BILLING_CONTRACT_VERSION } from './types.js';
|
|
2
|
-
export { createDomainEvent, isMandatoryEvent, MANDATORY_EVENT_TYPES, NoopEventPublisher, InMemoryEventPublisher } from './events.js';
|
|
1
|
+
export { isRetryableProviderError, CANONICAL_PROVIDER_ERROR_MESSAGES, SUBSCRIPTION_BILLING_CONTRACT_VERSION, } from './types.js';
|
|
2
|
+
export { createDomainEvent, isMandatoryEvent, MANDATORY_EVENT_TYPES, NoopEventPublisher, InMemoryEventPublisher, } from './events.js';
|
|
3
3
|
export { applySubscriptionEvent, changePlan, cancelSubscription, startTrial } from './reconcile.js';
|
|
4
4
|
// DEFAULT_DUNNING_STEPS/DunningStep/DunningStepDue sao os MESMOS simbolos ja
|
|
5
5
|
// exportados por `../billing/dunning.js` no barrel do pacote (`src/index.ts`) —
|
|
@@ -12,5 +12,6 @@ export { DisabledSubscriptionProvider } from './provider/disabled.js';
|
|
|
12
12
|
// ── BILL-01 (Fase 17): persistência + serviço do Billing SaaS ────────────────
|
|
13
13
|
export { SAAS_PLANS, DEFAULT_TRIAL_DAYS } from './plans.js';
|
|
14
14
|
export { ensureSaasPlanCatalog, listPublicPlans, getPlan, getSubscription, getSubscriptionByTenant, upsertSubscription, listInvoices, listBillingEvents, withOperatorContext, } from './repository.js';
|
|
15
|
-
export { seedSaasPlans, signupSelfService, subscriptionOverview, standingFor, entitlementsForPlan, startCheckout, processWebhook, changePlanForTenant, cancelForTenant, reactivateForTenant, backofficeListSubscriptions, backofficeOverview, backofficeListWebhookEvents, backofficeActivateSubscription, retryFailedWebhookEvents, runBillingCron, } from './service.js';
|
|
15
|
+
export { seedSaasPlans, signupSelfService, provisionAccountingOffice, subscriptionOverview, standingFor, entitlementsForPlan, startCheckout, processWebhook, changePlanForTenant, cancelForTenant, reactivateForTenant, backofficeListSubscriptions, backofficeOverview, backofficeListWebhookEvents, backofficeActivateSubscription, backofficeSetPlatformBillingExemption, retryFailedWebhookEvents, runBillingCron, } from './service.js';
|
|
16
|
+
export { readTenantPlatformBilling, setTenantPlatformBilling, isPlatformBillingExempt, standardPlatformBilling, PlatformBillingExemptError, } from './platform-exemption.js';
|
|
16
17
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/subscription-billing/index.ts"],"names":[],"mappings":"AAuBA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/subscription-billing/index.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,wBAAwB,EACxB,iCAAiC,EACjC,qCAAqC,GACtC,MAAM,YAAY,CAAC;AAQpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEpG,6EAA6E;AAC7E,gFAAgF;AAChF,0EAA0E;AAC1E,2BAA2B;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,kCAAkC,EAAE,MAAM,wBAAwB,CAAC;AAE5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAEtE,gFAAgF;AAChF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,OAAO,EACP,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,EACpB,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,kBAAkB,EAClB,2BAA2B,EAC3B,8BAA8B,EAC9B,qCAAqC,EACrC,wBAAwB,EACxB,cAAc,GACf,MAAM,cAAc,CAAC;AActB,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Tx } from '../db/client.js';
|
|
2
|
+
/**
|
|
3
|
+
* A cobrança da PLATAFORMA — e a isenção do escritório fundador.
|
|
4
|
+
*
|
|
5
|
+
* ## As duas cobranças que este produto tem, e o custo de confundi-las
|
|
6
|
+
*
|
|
7
|
+
* plataforma Baruk → escritório, pela assinatura do Office.
|
|
8
|
+
* escritório escritório → clientes dele, pelos honorários.
|
|
9
|
+
*
|
|
10
|
+
* O escritório fundador não paga a primeira. As duas formas erradas de
|
|
11
|
+
* implementar isso já custaram caro em outros produtos:
|
|
12
|
+
*
|
|
13
|
+
* **Desligar o financeiro dele.** Apagaria a SEGUNDA cobrança — que é o produto
|
|
14
|
+
* inteiro, e a razão de o escritório usar o Office. Isento de assinatura não é
|
|
15
|
+
* isento de operar.
|
|
16
|
+
*
|
|
17
|
+
* **`if (tenant.code === 'sc')`.** Faz o segundo escritório fundador virar um
|
|
18
|
+
* deploy, e a decisão comercial some dentro de um `if` que ninguém audita. É por
|
|
19
|
+
* isso que este módulo não conhece nenhum código de escritório: ele lê uma linha
|
|
20
|
+
* de configuração, e quem a escreveu está gravado nela.
|
|
21
|
+
*
|
|
22
|
+
* ## Quem escreve não é quem é cobrado
|
|
23
|
+
*
|
|
24
|
+
* A 0060 dá a `tenant_platform_billing` políticas POR COMANDO: o tenant lê a
|
|
25
|
+
* própria linha; só o operador da plataforma escreve. Um controle que o
|
|
26
|
+
* controlado pudesse gravar não seria controle — todo escritório seria fundador
|
|
27
|
+
* na primeira tarde.
|
|
28
|
+
*/
|
|
29
|
+
export type PlatformBillingMode = 'standard' | 'exempt';
|
|
30
|
+
export type PlatformExemptionReason = 'founding_tenant' | 'internal' | 'partner';
|
|
31
|
+
export interface TenantPlatformBilling {
|
|
32
|
+
tenantId: string;
|
|
33
|
+
billingMode: PlatformBillingMode;
|
|
34
|
+
exemptionReason: PlatformExemptionReason | null;
|
|
35
|
+
foundingTenant: boolean;
|
|
36
|
+
grantedBy: string | null;
|
|
37
|
+
grantedAt: string | null;
|
|
38
|
+
/** Isenção com prazo. `null` = sem prazo, que é o caso do fundador. */
|
|
39
|
+
expiresOn: string | null;
|
|
40
|
+
notes: string | null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A leitura padrão para quem não tem linha: cobrança normal.
|
|
44
|
+
*
|
|
45
|
+
* Ausência NUNCA vira isenção. Se a tabela sumisse, se a RLS escondesse a linha,
|
|
46
|
+
* ou se o tenant fosse novo, a resposta é a que cobra — errar para o lado de
|
|
47
|
+
* cobrar é recuperável com um estorno; errar para o lado de isentar em silêncio
|
|
48
|
+
* é receita que ninguém percebe faltando.
|
|
49
|
+
*/
|
|
50
|
+
export declare function standardPlatformBilling(tenantId: string): TenantPlatformBilling;
|
|
51
|
+
/**
|
|
52
|
+
* Lê a configuração de cobrança do tenant corrente.
|
|
53
|
+
*
|
|
54
|
+
* Tolera a ausência da tabela (`42P01`): um banco que ainda não aplicou a 0060
|
|
55
|
+
* responde "cobrança padrão", que é o comportamento anterior — e não uma exceção
|
|
56
|
+
* que derruba o checkout.
|
|
57
|
+
*/
|
|
58
|
+
export declare function readTenantPlatformBilling(tx: Tx, tenantId: string): Promise<TenantPlatformBilling>;
|
|
59
|
+
/**
|
|
60
|
+
* A isenção vale AGORA?
|
|
61
|
+
*
|
|
62
|
+
* Uma isenção com `expires_on` vencido volta a cobrar sozinha. Sem isso, uma
|
|
63
|
+
* cortesia de três meses concedida em janeiro seguiria valendo em dezembro, e
|
|
64
|
+
* ninguém olharia — a mesma classe de defeito do token de 60 dias que só é
|
|
65
|
+
* descoberto por uma cobrança que não saiu.
|
|
66
|
+
*/
|
|
67
|
+
export declare function isPlatformBillingExempt(record: TenantPlatformBilling, now?: Date): boolean;
|
|
68
|
+
/** Erro de quem tenta cobrar um tenant isento. Classe, para a rota traduzir. */
|
|
69
|
+
export declare class PlatformBillingExemptError extends Error {
|
|
70
|
+
readonly reason: PlatformExemptionReason | null;
|
|
71
|
+
constructor(reason: PlatformExemptionReason | null);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Escreve a configuração. SÓ o operador da plataforma chega aqui.
|
|
75
|
+
*
|
|
76
|
+
* A função não confere o privilégio: a RLS da 0060 confere, e é ela quem tem de
|
|
77
|
+
* conferir. Uma checagem em TypeScript aqui daria a impressão de ser o controle,
|
|
78
|
+
* e sobreviveria a alguém apagar as políticas.
|
|
79
|
+
*/
|
|
80
|
+
export declare function setTenantPlatformBilling(tx: Tx, input: {
|
|
81
|
+
tenantId: string;
|
|
82
|
+
billingMode: PlatformBillingMode;
|
|
83
|
+
exemptionReason?: PlatformExemptionReason | null;
|
|
84
|
+
foundingTenant?: boolean;
|
|
85
|
+
grantedBy: string | null;
|
|
86
|
+
expiresOn?: string | null;
|
|
87
|
+
notes?: string | null;
|
|
88
|
+
}): Promise<TenantPlatformBilling>;
|
|
89
|
+
//# sourceMappingURL=platform-exemption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-exemption.d.ts","sourceRoot":"","sources":["../../src/subscription-billing/platform-exemption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,QAAQ,CAAC;AACxD,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,mBAAmB,CAAC;IACjC,eAAe,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAChD,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uEAAuE;IACvE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAW/E;AA6BD;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,CAAC,CAWhC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,qBAAqB,EAC7B,GAAG,GAAE,IAAiB,GACrB,OAAO,CAIT;AAED,gFAAgF;AAChF,qBAAa,0BAA2B,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI;gBAAtC,MAAM,EAAE,uBAAuB,GAAG,IAAI;CAI5D;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,EAAE,EACN,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,mBAAmB,CAAC;IACjC,eAAe,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACjD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,GACA,OAAO,CAAC,qBAAqB,CAAC,CAyBhC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A leitura padrão para quem não tem linha: cobrança normal.
|
|
3
|
+
*
|
|
4
|
+
* Ausência NUNCA vira isenção. Se a tabela sumisse, se a RLS escondesse a linha,
|
|
5
|
+
* ou se o tenant fosse novo, a resposta é a que cobra — errar para o lado de
|
|
6
|
+
* cobrar é recuperável com um estorno; errar para o lado de isentar em silêncio
|
|
7
|
+
* é receita que ninguém percebe faltando.
|
|
8
|
+
*/
|
|
9
|
+
export function standardPlatformBilling(tenantId) {
|
|
10
|
+
return {
|
|
11
|
+
tenantId,
|
|
12
|
+
billingMode: 'standard',
|
|
13
|
+
exemptionReason: null,
|
|
14
|
+
foundingTenant: false,
|
|
15
|
+
grantedBy: null,
|
|
16
|
+
grantedAt: null,
|
|
17
|
+
expiresOn: null,
|
|
18
|
+
notes: null,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const COLUMNS = `tenant_id, billing_mode, exemption_reason, founding_tenant,
|
|
22
|
+
granted_by, granted_at, expires_on, notes`;
|
|
23
|
+
function map(r) {
|
|
24
|
+
return {
|
|
25
|
+
tenantId: r.tenant_id,
|
|
26
|
+
billingMode: r.billing_mode,
|
|
27
|
+
exemptionReason: r.exemption_reason,
|
|
28
|
+
foundingTenant: r.founding_tenant,
|
|
29
|
+
grantedBy: r.granted_by,
|
|
30
|
+
grantedAt: r.granted_at?.toISOString() ?? null,
|
|
31
|
+
expiresOn: r.expires_on ? r.expires_on.toISOString().slice(0, 10) : null,
|
|
32
|
+
notes: r.notes,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Lê a configuração de cobrança do tenant corrente.
|
|
37
|
+
*
|
|
38
|
+
* Tolera a ausência da tabela (`42P01`): um banco que ainda não aplicou a 0060
|
|
39
|
+
* responde "cobrança padrão", que é o comportamento anterior — e não uma exceção
|
|
40
|
+
* que derruba o checkout.
|
|
41
|
+
*/
|
|
42
|
+
export async function readTenantPlatformBilling(tx, tenantId) {
|
|
43
|
+
try {
|
|
44
|
+
const rows = await tx `
|
|
45
|
+
SELECT ${tx.unsafe(COLUMNS)} FROM tenant_platform_billing WHERE tenant_id = ${tenantId}
|
|
46
|
+
`;
|
|
47
|
+
return rows[0] ? map(rows[0]) : standardPlatformBilling(tenantId);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const code = err?.code;
|
|
51
|
+
if (code === '42P01' || code === '42703')
|
|
52
|
+
return standardPlatformBilling(tenantId);
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A isenção vale AGORA?
|
|
58
|
+
*
|
|
59
|
+
* Uma isenção com `expires_on` vencido volta a cobrar sozinha. Sem isso, uma
|
|
60
|
+
* cortesia de três meses concedida em janeiro seguiria valendo em dezembro, e
|
|
61
|
+
* ninguém olharia — a mesma classe de defeito do token de 60 dias que só é
|
|
62
|
+
* descoberto por uma cobrança que não saiu.
|
|
63
|
+
*/
|
|
64
|
+
export function isPlatformBillingExempt(record, now = new Date()) {
|
|
65
|
+
if (record.billingMode !== 'exempt')
|
|
66
|
+
return false;
|
|
67
|
+
if (!record.expiresOn)
|
|
68
|
+
return true;
|
|
69
|
+
return record.expiresOn >= now.toISOString().slice(0, 10);
|
|
70
|
+
}
|
|
71
|
+
/** Erro de quem tenta cobrar um tenant isento. Classe, para a rota traduzir. */
|
|
72
|
+
export class PlatformBillingExemptError extends Error {
|
|
73
|
+
reason;
|
|
74
|
+
constructor(reason) {
|
|
75
|
+
super(`tenant isento da assinatura da plataforma (${reason ?? 'sem motivo registrado'})`);
|
|
76
|
+
this.reason = reason;
|
|
77
|
+
this.name = 'PlatformBillingExemptError';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Escreve a configuração. SÓ o operador da plataforma chega aqui.
|
|
82
|
+
*
|
|
83
|
+
* A função não confere o privilégio: a RLS da 0060 confere, e é ela quem tem de
|
|
84
|
+
* conferir. Uma checagem em TypeScript aqui daria a impressão de ser o controle,
|
|
85
|
+
* e sobreviveria a alguém apagar as políticas.
|
|
86
|
+
*/
|
|
87
|
+
export async function setTenantPlatformBilling(tx, input) {
|
|
88
|
+
const exempt = input.billingMode === 'exempt';
|
|
89
|
+
const rows = await tx `
|
|
90
|
+
INSERT INTO tenant_platform_billing (
|
|
91
|
+
tenant_id, billing_mode, exemption_reason, founding_tenant,
|
|
92
|
+
granted_by, granted_at, expires_on, notes
|
|
93
|
+
) VALUES (
|
|
94
|
+
${input.tenantId}, ${input.billingMode},
|
|
95
|
+
${exempt ? (input.exemptionReason ?? 'internal') : null},
|
|
96
|
+
${input.foundingTenant ?? false}, ${input.grantedBy},
|
|
97
|
+
${exempt ? new Date().toISOString() : null},
|
|
98
|
+
${input.expiresOn ?? null}, ${input.notes ?? null}
|
|
99
|
+
)
|
|
100
|
+
ON CONFLICT (tenant_id) DO UPDATE SET
|
|
101
|
+
billing_mode = EXCLUDED.billing_mode,
|
|
102
|
+
exemption_reason = EXCLUDED.exemption_reason,
|
|
103
|
+
founding_tenant = EXCLUDED.founding_tenant,
|
|
104
|
+
granted_by = EXCLUDED.granted_by,
|
|
105
|
+
granted_at = EXCLUDED.granted_at,
|
|
106
|
+
expires_on = EXCLUDED.expires_on,
|
|
107
|
+
notes = EXCLUDED.notes,
|
|
108
|
+
updated_at = now()
|
|
109
|
+
RETURNING ${tx.unsafe(COLUMNS)}
|
|
110
|
+
`;
|
|
111
|
+
return map(rows[0]);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=platform-exemption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-exemption.js","sourceRoot":"","sources":["../../src/subscription-billing/platform-exemption.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Db } from '../db/client.js';
|
|
2
2
|
import type { EntitlementRecord } from '../entitlements/types.js';
|
|
3
|
+
import { type PlatformBillingMode, type PlatformExemptionReason, type TenantPlatformBilling } from './platform-exemption.js';
|
|
3
4
|
import type { BillingMode, SubscriptionStatus, WebhookHeaders } from './types.js';
|
|
4
5
|
import { ensureSaasPlanCatalog, getPlan, listBillingEvents, listInvoices, listPublicPlans, type SaasPlanRow, type SubscriptionRow } from './repository.js';
|
|
5
6
|
import { type ProductBillingRegistry } from './product-config.js';
|
|
@@ -54,6 +55,27 @@ export interface SignupResult {
|
|
|
54
55
|
planKey: string;
|
|
55
56
|
trialEndsAt: string;
|
|
56
57
|
}
|
|
58
|
+
export interface ProvisionOfficeInput {
|
|
59
|
+
companyName: string;
|
|
60
|
+
ownerEmail: string;
|
|
61
|
+
ownerFullName: string;
|
|
62
|
+
planKey?: string;
|
|
63
|
+
/** Usuário da operadora que provisiona — vira `invited_by` e ator da trilha. */
|
|
64
|
+
operatorUserId: string;
|
|
65
|
+
ip?: string | null;
|
|
66
|
+
userAgent?: string | null;
|
|
67
|
+
}
|
|
68
|
+
export interface ProvisionOfficeResult {
|
|
69
|
+
tenantId: string;
|
|
70
|
+
tenantCode: string;
|
|
71
|
+
ownerUserId: string;
|
|
72
|
+
ownerEmail: string;
|
|
73
|
+
planKey: string;
|
|
74
|
+
trialEndsAt: string;
|
|
75
|
+
/** Token de ativação do dono. A borda HTTP compõe o link e envia o e-mail. */
|
|
76
|
+
activationToken: string | null;
|
|
77
|
+
}
|
|
78
|
+
export declare function provisionAccountingOffice(db: Db, input: ProvisionOfficeInput, nowIso: string): Promise<ProvisionOfficeResult>;
|
|
57
79
|
/**
|
|
58
80
|
* Cadastro self-service (Fase 17): cria usuário + tenant em TRIAL + organização +
|
|
59
81
|
* membership com papel `owner` + entitlement do produto + assinatura `trialing`.
|
|
@@ -74,6 +96,14 @@ export interface SubscriptionOverview {
|
|
|
74
96
|
invoices: Awaited<ReturnType<typeof listInvoices>>;
|
|
75
97
|
entitlements: EntitlementRecord[];
|
|
76
98
|
events: Awaited<ReturnType<typeof listBillingEvents>>;
|
|
99
|
+
/**
|
|
100
|
+
* Como a PLATAFORMA cobra este escritório. Vai junto do standing porque a tela
|
|
101
|
+
* precisa das duas coisas para não mentir: um tenant isento sem assinatura tem
|
|
102
|
+
* `standing.reason = 'none'`, e mostrar só isso diria "sem assinatura" a quem
|
|
103
|
+
* está isento por decisão comercial.
|
|
104
|
+
*/
|
|
105
|
+
platformBilling: TenantPlatformBilling;
|
|
106
|
+
platformBillingExempt: boolean;
|
|
77
107
|
}
|
|
78
108
|
export declare function subscriptionOverview(db: Db, ctx: {
|
|
79
109
|
tenantId: string;
|
|
@@ -161,6 +191,50 @@ export declare function backofficeListWebhookEvents(db: Db, limit?: number): Pro
|
|
|
161
191
|
* simula uma fatura `received` e reconcilia pelo MESMO caminho do webhook —
|
|
162
192
|
* nenhuma transição de estado fora do domínio puro.
|
|
163
193
|
*/
|
|
194
|
+
/**
|
|
195
|
+
* A operadora declara — ou revoga — a isenção da assinatura de plataforma.
|
|
196
|
+
*
|
|
197
|
+
* ## Por que esta função existe, e por que ela não existia
|
|
198
|
+
*
|
|
199
|
+
* A C1 entregou `tenant_platform_billing` com RLS por comando e testes verdes, e
|
|
200
|
+
* a tabela terminou o deploy com ZERO linhas. Não por esquecimento: não havia
|
|
201
|
+
* caminho de produto para escrevê-la. `setTenantPlatformBilling` era exportada e
|
|
202
|
+
* alcançável só por código, o que na prática significa "alguém abre um console e
|
|
203
|
+
* roda um script" — exatamente o tipo de ato que a tabela existe para tornar
|
|
204
|
+
* auditável.
|
|
205
|
+
*
|
|
206
|
+
* Um mecanismo cujo único acionamento é um script fora do produto não é um
|
|
207
|
+
* mecanismo auditável; é um mecanismo com a auditoria de fora.
|
|
208
|
+
*
|
|
209
|
+
* ## Quem pode
|
|
210
|
+
*
|
|
211
|
+
* Só a OPERADORA (allowlist de e-mails do backoffice). O tenant não escreve a
|
|
212
|
+
* própria isenção — a RLS da 0060 já garante isso, e esta rota não é uma segunda
|
|
213
|
+
* barreira, é o caminho que atravessa a primeira legitimamente, com
|
|
214
|
+
* `withOperatorContext`.
|
|
215
|
+
*
|
|
216
|
+
* ## O que fica gravado
|
|
217
|
+
*
|
|
218
|
+
* `granted_by` é o USUÁRIO operador, não um rótulo. `granted_at` sai do banco.
|
|
219
|
+
* E a trilha registra o e-mail de quem decidiu, o motivo e o tenant — porque a
|
|
220
|
+
* pergunta que alguém vai fazer daqui a um ano é "quem isentou este escritório,
|
|
221
|
+
* quando e por quê", e ela não pode depender de memória.
|
|
222
|
+
*
|
|
223
|
+
* Revogar usa a mesma porta: `billingMode: 'standard'` limpa motivo e data, e o
|
|
224
|
+
* motor volta a cobrar. Uma isenção que só se concede é uma isenção permanente
|
|
225
|
+
* por acidente.
|
|
226
|
+
*/
|
|
227
|
+
export declare function backofficeSetPlatformBillingExemption(db: Db, operator: {
|
|
228
|
+
email: string;
|
|
229
|
+
userId: string;
|
|
230
|
+
}, input: {
|
|
231
|
+
tenantId: string;
|
|
232
|
+
billingMode: PlatformBillingMode;
|
|
233
|
+
exemptionReason?: PlatformExemptionReason | null;
|
|
234
|
+
foundingTenant?: boolean;
|
|
235
|
+
expiresOn?: string | null;
|
|
236
|
+
notes?: string | null;
|
|
237
|
+
}): Promise<TenantPlatformBilling>;
|
|
164
238
|
export declare function backofficeActivateSubscription(db: Db, operatorEmail: string, tenantId: string, planKey: string, nowIso: string): Promise<SubscriptionRow>;
|
|
165
239
|
/**
|
|
166
240
|
* Reprocessa eventos de webhook `failed` recentes (rede de segurança para o
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/subscription-billing/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAM,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/subscription-billing/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,16 +2,18 @@ import { ConflictError, NotFoundError, ValidationError, uuidv7 } from '@baruk/sh
|
|
|
2
2
|
import { withContext } from '../db/context.js';
|
|
3
3
|
import { appendAudit } from '../audit/audit.js';
|
|
4
4
|
import { hashPassword } from '../auth/password.js';
|
|
5
|
+
import { inviteUser } from '../users/repository.js';
|
|
5
6
|
import { assignSystemRole, ensureMembership, ensureOrganization, ensureTenant, } from '../tenancy/provisioning.js';
|
|
6
7
|
import { ensureProductCatalog, ensureTenantProduct } from '../products/repository.js';
|
|
7
8
|
import { deriveEntitlements } from '../entitlements/derive.js';
|
|
8
9
|
import { sendTransactionalOutbound } from '../mail/transactional-outbound.js';
|
|
9
10
|
import { applySubscriptionEvent, cancelSubscription, changePlan, startTrial } from './reconcile.js';
|
|
11
|
+
import { isPlatformBillingExempt, PlatformBillingExemptError, readTenantPlatformBilling, setTenantPlatformBilling, } from './platform-exemption.js';
|
|
10
12
|
import { dunningStepsAsEvents } from './dunning.js';
|
|
11
13
|
import { assertLiveProviderAllowed, readLiveRuntime } from '../billing/live-guard.js';
|
|
12
14
|
import { resolveSubscriptionBillingProvider } from './provider/registry.js';
|
|
13
15
|
import { appendDomainEvents, backofficeSummary, ensureSaasPlanCatalog, getPlan, getSubscription, insertWebhookEvent, listAllSubscriptions, listBillingEvents, listExecutedDunningSteps, listFailedWebhookEvents, listInvoices, listPublicPlans, listSubscriptionsForCron, lockTenantBilling, markWebhookEvent, recordDunningStep, setSubscriptionProviderRefs, upsertInvoice, upsertSubscription, withOperatorContext, } from './repository.js';
|
|
14
|
-
import { DEFAULT_PRODUCT_KEY, SAAS_PLANS } from './plans.js';
|
|
16
|
+
import { DEFAULT_PRODUCT_KEY, DEFAULT_TRIAL_DAYS, SAAS_PLANS } from './plans.js';
|
|
15
17
|
import { singleProductRegistry } from './product-config.js';
|
|
16
18
|
function asRegistry(source) {
|
|
17
19
|
return 'resolve' in source ? source : singleProductRegistry(source);
|
|
@@ -70,6 +72,68 @@ export async function seedSaasPlans(db) {
|
|
|
70
72
|
await ensureProductCatalog(db);
|
|
71
73
|
await ensureSaasPlanCatalog(db, SAAS_PLANS);
|
|
72
74
|
}
|
|
75
|
+
export async function provisionAccountingOffice(db, input, nowIso) {
|
|
76
|
+
const email = input.ownerEmail.trim().toLowerCase();
|
|
77
|
+
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email))
|
|
78
|
+
throw new ValidationError('E-mail inválido');
|
|
79
|
+
if (!input.companyName.trim())
|
|
80
|
+
throw new ValidationError('Nome do escritório é obrigatório');
|
|
81
|
+
if (!input.ownerFullName.trim())
|
|
82
|
+
throw new ValidationError('Nome do responsável é obrigatório');
|
|
83
|
+
const planKey = input.planKey ?? SAAS_PLANS.find((p) => p.isActive && p.isPublic)?.key;
|
|
84
|
+
if (!planKey)
|
|
85
|
+
throw new ValidationError('Nenhum plano ativo disponível');
|
|
86
|
+
const plan = await getPlan(db, planKey);
|
|
87
|
+
if (!plan || !plan.isActive)
|
|
88
|
+
throw new ValidationError(`Plano indisponível: ${planKey}`);
|
|
89
|
+
const code = await uniqueTenantCode(db, input.companyName);
|
|
90
|
+
const tenantId = await ensureTenant(db, {
|
|
91
|
+
code,
|
|
92
|
+
displayName: input.companyName.trim(),
|
|
93
|
+
status: 'trial',
|
|
94
|
+
primaryProduct: DEFAULT_PRODUCT_KEY,
|
|
95
|
+
});
|
|
96
|
+
await ensureOrganization(db, tenantId, input.companyName.trim());
|
|
97
|
+
await ensureProductCatalog(db);
|
|
98
|
+
await ensureTenantProduct(db, tenantId, DEFAULT_PRODUCT_KEY);
|
|
99
|
+
const trialEndsAt = addDays(nowIso, plan.trialDays > 0 ? plan.trialDays : DEFAULT_TRIAL_DAYS);
|
|
100
|
+
const { subscription, domainEvents } = startTrial(tenantId, plan.key, trialEndsAt, nowIso);
|
|
101
|
+
/*
|
|
102
|
+
* Contexto do TENANT NOVO com o usuário da OPERADORA.
|
|
103
|
+
*
|
|
104
|
+
* O operador não é membro deste escritório e nunca será — ele abre o contexto
|
|
105
|
+
* para criar o convite e sai. O `invited_by` aponta para ele, que é a
|
|
106
|
+
* resposta honesta a "quem colocou esta pessoa aqui".
|
|
107
|
+
*/
|
|
108
|
+
return withContext(db, { tenantId, userId: input.operatorUserId }, async (tx) => {
|
|
109
|
+
const invited = await inviteUser(tx, {
|
|
110
|
+
email,
|
|
111
|
+
fullName: input.ownerFullName.trim(),
|
|
112
|
+
roleKey: 'owner',
|
|
113
|
+
invitedBy: input.operatorUserId,
|
|
114
|
+
});
|
|
115
|
+
const row = await upsertSubscription(tx, { tenantId, planKey: plan.key, subscription });
|
|
116
|
+
await appendDomainEvents(tx, row.rowId, domainEvents);
|
|
117
|
+
await appendAudit(tx, {
|
|
118
|
+
actorId: input.operatorUserId,
|
|
119
|
+
action: 'tenant.provisioned_by_operator',
|
|
120
|
+
resourceType: 'tenant',
|
|
121
|
+
resourceId: tenantId,
|
|
122
|
+
metadata: { planKey: plan.key, trialEndsAt, tenantCode: code, ownerEmail: email },
|
|
123
|
+
ip: input.ip ?? null,
|
|
124
|
+
userAgent: input.userAgent ?? null,
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
tenantId,
|
|
128
|
+
tenantCode: code,
|
|
129
|
+
ownerUserId: invited.userId,
|
|
130
|
+
ownerEmail: invited.email,
|
|
131
|
+
planKey: plan.key,
|
|
132
|
+
trialEndsAt,
|
|
133
|
+
activationToken: invited.activationToken,
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
}
|
|
73
137
|
function slugify(name) {
|
|
74
138
|
return name
|
|
75
139
|
.normalize('NFD')
|
|
@@ -79,6 +143,31 @@ function slugify(name) {
|
|
|
79
143
|
.replace(/^-+|-+$/g, '')
|
|
80
144
|
.slice(0, 40);
|
|
81
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Código do escritório a partir do nome, único na base.
|
|
148
|
+
*
|
|
149
|
+
* Extraído do signup quando o provisionamento pela operadora passou a precisar
|
|
150
|
+
* do mesmo cálculo. Duas cópias da regra de colisão renderiam dois códigos
|
|
151
|
+
* diferentes para o mesmo nome dependendo de por qual porta o escritório
|
|
152
|
+
* entrou — e o código aparece em referência de cobrança já emitida.
|
|
153
|
+
*/
|
|
154
|
+
async function uniqueTenantCode(db, companyName) {
|
|
155
|
+
const base = slugify(companyName) || 'escritorio';
|
|
156
|
+
let code = base;
|
|
157
|
+
for (let i = 2;; i += 1) {
|
|
158
|
+
const clash = await db `
|
|
159
|
+
SELECT id FROM tenant WHERE lower(code) = lower(${code}) AND deleted_at IS NULL
|
|
160
|
+
`;
|
|
161
|
+
if (!clash[0])
|
|
162
|
+
break;
|
|
163
|
+
code = `${base}-${i}`;
|
|
164
|
+
if (i > 50) {
|
|
165
|
+
code = `${base}-${uuidv7().slice(-6)}`;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return code;
|
|
170
|
+
}
|
|
82
171
|
/**
|
|
83
172
|
* Cadastro self-service (Fase 17): cria usuário + tenant em TRIAL + organização +
|
|
84
173
|
* membership com papel `owner` + entitlement do produto + assinatura `trialing`.
|
|
@@ -103,20 +192,7 @@ export async function signupSelfService(db, input, nowIso) {
|
|
|
103
192
|
throw new ConflictError('Já existe uma conta com este e-mail. Faça login para continuar.');
|
|
104
193
|
}
|
|
105
194
|
// Código único do tenant a partir do nome (sufixo em caso de colisão).
|
|
106
|
-
const
|
|
107
|
-
let code = base;
|
|
108
|
-
for (let i = 2;; i += 1) {
|
|
109
|
-
const clash = await db `
|
|
110
|
-
SELECT id FROM tenant WHERE lower(code) = lower(${code}) AND deleted_at IS NULL
|
|
111
|
-
`;
|
|
112
|
-
if (!clash[0])
|
|
113
|
-
break;
|
|
114
|
-
code = `${base}-${i}`;
|
|
115
|
-
if (i > 50) {
|
|
116
|
-
code = `${base}-${uuidv7().slice(-6)}`;
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
195
|
+
const code = await uniqueTenantCode(db, input.companyName);
|
|
120
196
|
// INSERT puro (não upsert): o papel de app pode CRIAR credencial, nunca
|
|
121
197
|
// sobrescrever (REVOKE UPDATE em user_credential — anti account-takeover).
|
|
122
198
|
// A checagem de e-mail acima já garante que o usuário é novo.
|
|
@@ -191,12 +267,13 @@ export function entitlementsForPlan(sub, plan, nowIso) {
|
|
|
191
267
|
});
|
|
192
268
|
}
|
|
193
269
|
export async function subscriptionOverview(db, ctx, nowIso) {
|
|
194
|
-
const { sub, invoices, events } = await withContext(db, ctx, async (tx) => {
|
|
270
|
+
const { sub, invoices, events, platformBilling } = await withContext(db, ctx, async (tx) => {
|
|
195
271
|
const sub0 = await getSubscription(tx);
|
|
196
272
|
return {
|
|
197
273
|
sub: sub0,
|
|
198
274
|
invoices: sub0 ? await listInvoices(tx) : [],
|
|
199
275
|
events: sub0 ? await listBillingEvents(tx, 20) : [],
|
|
276
|
+
platformBilling: await readTenantPlatformBilling(tx, ctx.tenantId),
|
|
200
277
|
};
|
|
201
278
|
});
|
|
202
279
|
// Fora da transação: getPlan usa outra conexão do pool — dentro dela seria
|
|
@@ -209,6 +286,8 @@ export async function subscriptionOverview(db, ctx, nowIso) {
|
|
|
209
286
|
invoices,
|
|
210
287
|
entitlements: entitlementsForPlan(sub, plan, nowIso),
|
|
211
288
|
events,
|
|
289
|
+
platformBilling,
|
|
290
|
+
platformBillingExempt: isPlatformBillingExempt(platformBilling),
|
|
212
291
|
};
|
|
213
292
|
}
|
|
214
293
|
/**
|
|
@@ -230,6 +309,21 @@ export async function startCheckout(db, ctx, source, planKey, _nowIso, productKe
|
|
|
230
309
|
// A conta de gateway e a URL de retorno saem do PRODUTO do plano — nunca de
|
|
231
310
|
// uma configuração global. É isso que impede o checkout de um produto voltar
|
|
232
311
|
// para o domínio de outro, ou cobrar na conta errada.
|
|
312
|
+
// ═══ O portão da isenção vem ANTES do gateway ═════════════════════════════
|
|
313
|
+
//
|
|
314
|
+
// Um tenant isento da assinatura da plataforma não deve nem chegar a existir
|
|
315
|
+
// como cliente no gateway: `ensureCustomer` cria cadastro, `createCheckout`
|
|
316
|
+
// cria link de cobrança, e um link emitido é uma cobrança que alguém pode
|
|
317
|
+
// pagar. Recusar depois — ao reconciliar o webhook — já teria custado dinheiro
|
|
318
|
+
// ao escritório fundador.
|
|
319
|
+
//
|
|
320
|
+
// A isenção NÃO desliga o financeiro do escritório: `receivable`, honorários e
|
|
321
|
+
// régua continuam intactos. O que ela desliga é a cobrança que a Baruk faz ao
|
|
322
|
+
// escritório, e só ela.
|
|
323
|
+
const billing = await withContext(db, ctx, (tx) => readTenantPlatformBilling(tx, ctx.tenantId));
|
|
324
|
+
if (isPlatformBillingExempt(billing)) {
|
|
325
|
+
throw new PlatformBillingExemptError(billing.exemptionReason);
|
|
326
|
+
}
|
|
233
327
|
const cfg = asRegistry(source).resolve({ productKey: plan.productKey, tenantId: ctx.tenantId });
|
|
234
328
|
const provider = providerFor(cfg);
|
|
235
329
|
if (provider.mode === 'disabled') {
|
|
@@ -614,6 +708,78 @@ export async function backofficeListWebhookEvents(db, limit = 100) {
|
|
|
614
708
|
* simula uma fatura `received` e reconcilia pelo MESMO caminho do webhook —
|
|
615
709
|
* nenhuma transição de estado fora do domínio puro.
|
|
616
710
|
*/
|
|
711
|
+
/**
|
|
712
|
+
* A operadora declara — ou revoga — a isenção da assinatura de plataforma.
|
|
713
|
+
*
|
|
714
|
+
* ## Por que esta função existe, e por que ela não existia
|
|
715
|
+
*
|
|
716
|
+
* A C1 entregou `tenant_platform_billing` com RLS por comando e testes verdes, e
|
|
717
|
+
* a tabela terminou o deploy com ZERO linhas. Não por esquecimento: não havia
|
|
718
|
+
* caminho de produto para escrevê-la. `setTenantPlatformBilling` era exportada e
|
|
719
|
+
* alcançável só por código, o que na prática significa "alguém abre um console e
|
|
720
|
+
* roda um script" — exatamente o tipo de ato que a tabela existe para tornar
|
|
721
|
+
* auditável.
|
|
722
|
+
*
|
|
723
|
+
* Um mecanismo cujo único acionamento é um script fora do produto não é um
|
|
724
|
+
* mecanismo auditável; é um mecanismo com a auditoria de fora.
|
|
725
|
+
*
|
|
726
|
+
* ## Quem pode
|
|
727
|
+
*
|
|
728
|
+
* Só a OPERADORA (allowlist de e-mails do backoffice). O tenant não escreve a
|
|
729
|
+
* própria isenção — a RLS da 0060 já garante isso, e esta rota não é uma segunda
|
|
730
|
+
* barreira, é o caminho que atravessa a primeira legitimamente, com
|
|
731
|
+
* `withOperatorContext`.
|
|
732
|
+
*
|
|
733
|
+
* ## O que fica gravado
|
|
734
|
+
*
|
|
735
|
+
* `granted_by` é o USUÁRIO operador, não um rótulo. `granted_at` sai do banco.
|
|
736
|
+
* E a trilha registra o e-mail de quem decidiu, o motivo e o tenant — porque a
|
|
737
|
+
* pergunta que alguém vai fazer daqui a um ano é "quem isentou este escritório,
|
|
738
|
+
* quando e por quê", e ela não pode depender de memória.
|
|
739
|
+
*
|
|
740
|
+
* Revogar usa a mesma porta: `billingMode: 'standard'` limpa motivo e data, e o
|
|
741
|
+
* motor volta a cobrar. Uma isenção que só se concede é uma isenção permanente
|
|
742
|
+
* por acidente.
|
|
743
|
+
*/
|
|
744
|
+
export async function backofficeSetPlatformBillingExemption(db, operator, input) {
|
|
745
|
+
const tenants = await db `
|
|
746
|
+
SELECT id FROM tenant WHERE id = ${input.tenantId} AND deleted_at IS NULL
|
|
747
|
+
`;
|
|
748
|
+
if (!tenants[0])
|
|
749
|
+
throw new ValidationError(`Tenant desconhecido: ${input.tenantId}`);
|
|
750
|
+
const record = await withOperatorContext(db, (tx) => setTenantPlatformBilling(tx, {
|
|
751
|
+
tenantId: input.tenantId,
|
|
752
|
+
billingMode: input.billingMode,
|
|
753
|
+
exemptionReason: input.exemptionReason ?? null,
|
|
754
|
+
foundingTenant: input.foundingTenant ?? false,
|
|
755
|
+
grantedBy: operator.userId,
|
|
756
|
+
expiresOn: input.expiresOn ?? null,
|
|
757
|
+
notes: input.notes ?? null,
|
|
758
|
+
}));
|
|
759
|
+
/*
|
|
760
|
+
* A trilha é escrita no contexto do TENANT afetado, e não no do operador: é lá
|
|
761
|
+
* que alguém vai procurar por que aquele escritório não é cobrado. `audit_log`
|
|
762
|
+
* é tenant-scoped, e gravar no lugar errado é o mesmo que não gravar.
|
|
763
|
+
*/
|
|
764
|
+
await withContext(db, { tenantId: input.tenantId, userId: operator.userId }, (tx) => appendAudit(tx, {
|
|
765
|
+
actorType: 'user',
|
|
766
|
+
actorId: operator.userId,
|
|
767
|
+
action: record.billingMode === 'exempt'
|
|
768
|
+
? 'platform_billing_exemption_granted'
|
|
769
|
+
: 'platform_billing_exemption_revoked',
|
|
770
|
+
resourceType: 'tenant_platform_billing',
|
|
771
|
+
resourceId: null,
|
|
772
|
+
metadata: {
|
|
773
|
+
operatorEmail: operator.email,
|
|
774
|
+
billingMode: record.billingMode,
|
|
775
|
+
exemptionReason: record.exemptionReason,
|
|
776
|
+
foundingTenant: record.foundingTenant,
|
|
777
|
+
expiresOn: record.expiresOn,
|
|
778
|
+
notes: record.notes,
|
|
779
|
+
},
|
|
780
|
+
}));
|
|
781
|
+
return record;
|
|
782
|
+
}
|
|
617
783
|
export async function backofficeActivateSubscription(db, operatorEmail, tenantId, planKey, nowIso) {
|
|
618
784
|
const plan = await getPlan(db, planKey);
|
|
619
785
|
if (!plan)
|