@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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
-- 0051 — os 17 seeds viram regras, SEM ganhar precisão que não têm.
|
|
2
|
+
--
|
|
3
|
+
-- ═══ O risco que esta migration precisa não correr ═════════════════════════
|
|
4
|
+
--
|
|
5
|
+
-- É tentador aproveitar a estrutura nova para "melhorar" o seed: dar UF ao ISS,
|
|
6
|
+
-- marcar as federais como validadas, escrever condição de folha nos itens
|
|
7
|
+
-- trabalhistas. Cada uma dessas seria legislação inventada por quem não tem
|
|
8
|
+
-- competência para inventá-la — e escrita num lugar em que passaria a parecer
|
|
9
|
+
-- fonte.
|
|
10
|
+
--
|
|
11
|
+
-- Então esta migration converte o que existe, e **nada mais**:
|
|
12
|
+
--
|
|
13
|
+
-- • toda regra nasce `pending_validation`. Nenhuma vira `validated`: ninguém
|
|
14
|
+
-- conferiu nada ainda, e o CHECK do banco exige autor para validar;
|
|
15
|
+
-- • toda condição nasce `{"op":"always"}` — a aplicabilidade que o seed de
|
|
16
|
+
-- fato tem hoje é por regime, e o regime já é filtrado por
|
|
17
|
+
-- `applies_to_regime` no tipo de item. Não invento condição de folha;
|
|
18
|
+
-- • os dois itens de esfera local viram `not_configured`, porque **não se
|
|
19
|
+
-- sabe de qual UF nem de qual município eles são**. Dar-lhes uma
|
|
20
|
+
-- jurisdição seria escolher um estado por conta própria.
|
|
21
|
+
--
|
|
22
|
+
-- `valid_from` é a data desta migration: é honesto dizer "esta regra existe no
|
|
23
|
+
-- sistema desde hoje", e desonesto dizer que ela vale desde sempre.
|
|
24
|
+
|
|
25
|
+
DO $$
|
|
26
|
+
DECLARE
|
|
27
|
+
r record;
|
|
28
|
+
hoje date := CURRENT_DATE;
|
|
29
|
+
BEGIN
|
|
30
|
+
FOR r IN
|
|
31
|
+
SELECT id, key, sphere, due_rule, note
|
|
32
|
+
FROM recurring_item_type
|
|
33
|
+
WHERE tenant_id IS NULL AND deleted_at IS NULL
|
|
34
|
+
LOOP
|
|
35
|
+
-- Idempotente: reexecutar não duplica.
|
|
36
|
+
IF EXISTS (SELECT 1 FROM fiscal_rule WHERE item_type_id = r.id AND tenant_id IS NULL) THEN
|
|
37
|
+
CONTINUE;
|
|
38
|
+
END IF;
|
|
39
|
+
|
|
40
|
+
IF r.sphere IN ('estadual', 'municipal') THEN
|
|
41
|
+
-- Marcador honesto: o item existe, a regra não. Sem UF, sem município e
|
|
42
|
+
-- sem vencimento — o motor devolve RULE_NOT_CONFIGURED e ninguém gera
|
|
43
|
+
-- obrigação local por engano.
|
|
44
|
+
--
|
|
45
|
+
-- Fica como `federal` no campo de escopo apenas porque o CHECK exige
|
|
46
|
+
-- jurisdição completa para state/municipal, e completá-la seria inventar.
|
|
47
|
+
-- O `status` é quem carrega a verdade: não configurada.
|
|
48
|
+
INSERT INTO fiscal_rule (
|
|
49
|
+
id, tenant_id, item_type_id, jurisdiction_scope, version, valid_from,
|
|
50
|
+
status, conditions, due_rule, note
|
|
51
|
+
) VALUES (
|
|
52
|
+
gen_random_uuid(), NULL, r.id, 'federal', 1, hoje,
|
|
53
|
+
'not_configured', '{"op":"always"}'::jsonb, NULL,
|
|
54
|
+
coalesce(r.note || ' ', '') ||
|
|
55
|
+
'[N1] Item de esfera ' || r.sphere || ' sem jurisdição definida. ' ||
|
|
56
|
+
'Cadastre uma regra por UF (ou por município) antes de gerar.'
|
|
57
|
+
);
|
|
58
|
+
ELSE
|
|
59
|
+
INSERT INTO fiscal_rule (
|
|
60
|
+
id, tenant_id, item_type_id, jurisdiction_scope, version, valid_from,
|
|
61
|
+
status, conditions, due_rule, note
|
|
62
|
+
) VALUES (
|
|
63
|
+
gen_random_uuid(), NULL, r.id, 'federal', 1, hoje,
|
|
64
|
+
'pending_validation', '{"op":"always"}'::jsonb, r.due_rule,
|
|
65
|
+
coalesce(r.note, '')
|
|
66
|
+
);
|
|
67
|
+
END IF;
|
|
68
|
+
END LOOP;
|
|
69
|
+
END $$;
|
|
70
|
+
|
|
71
|
+
COMMENT ON TABLE fiscal_rule IS
|
|
72
|
+
'Regra fiscal versionada por jurisdição. As 17 primeiras vieram do seed inicial e nascem PENDING_VALIDATION ou NOT_CONFIGURED — nenhuma foi conferida por pessoa, e nenhuma ganhou jurisdição ou prazo que o seed não tinha.';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
-- 0052 — fechar o DELETE da regra fiscal GLOBAL.
|
|
2
|
+
--
|
|
3
|
+
-- ═══ O defeito, encontrado pelo teste antes do deploy ══════════════════════
|
|
4
|
+
--
|
|
5
|
+
-- A 0049 criou uma política única para `fiscal_rule`:
|
|
6
|
+
--
|
|
7
|
+
-- USING (tenant_id IS NULL OR tenant_id = current_tenant)
|
|
8
|
+
-- WITH CHECK (tenant_id = current_tenant)
|
|
9
|
+
--
|
|
10
|
+
-- Esse par fecha INSERT e UPDATE — e **não fecha DELETE**. `WITH CHECK` só
|
|
11
|
+
-- governa a linha que passa a existir; quem decide o que um DELETE alcança é o
|
|
12
|
+
-- `USING`. Com o ramo `IS NULL` ali, qualquer escritório apagava regra fiscal
|
|
13
|
+
-- nacional: as regras de todos os outros escritórios do país.
|
|
14
|
+
--
|
|
15
|
+
-- É a mesma forma do P0-A da Fase 4 — o ramo `IS NULL` no lugar errado — com
|
|
16
|
+
-- um agravante: lá a barreira de privilégio segurava, porque `role` teve
|
|
17
|
+
-- INSERT/UPDATE/DELETE revogados do runtime. Aqui não dá para revogar: o
|
|
18
|
+
-- escritório precisa escrever as PRÓPRIAS regras. A separação tem de vir da
|
|
19
|
+
-- política.
|
|
20
|
+
--
|
|
21
|
+
-- ═══ A correção ════════════════════════════════════════════════════════════
|
|
22
|
+
--
|
|
23
|
+
-- Uma política por comando, em vez de uma para tudo. Ler o catálogo nacional é
|
|
24
|
+
-- direito de todos; alterá-lo, de ninguém que opere como escritório.
|
|
25
|
+
|
|
26
|
+
DROP POLICY IF EXISTS fiscal_rule_visibility ON fiscal_rule;
|
|
27
|
+
|
|
28
|
+
CREATE POLICY fiscal_rule_read ON fiscal_rule
|
|
29
|
+
FOR SELECT
|
|
30
|
+
USING (tenant_id IS NULL OR tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
31
|
+
|
|
32
|
+
CREATE POLICY fiscal_rule_insert ON fiscal_rule
|
|
33
|
+
FOR INSERT
|
|
34
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
35
|
+
|
|
36
|
+
CREATE POLICY fiscal_rule_update ON fiscal_rule
|
|
37
|
+
FOR UPDATE
|
|
38
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
39
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
40
|
+
|
|
41
|
+
CREATE POLICY fiscal_rule_delete ON fiscal_rule
|
|
42
|
+
FOR DELETE
|
|
43
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
44
|
+
|
|
45
|
+
COMMENT ON POLICY fiscal_rule_read ON fiscal_rule IS
|
|
46
|
+
'Leitura: catálogo nacional + regras do próprio escritório.';
|
|
47
|
+
COMMENT ON POLICY fiscal_rule_delete ON fiscal_rule IS
|
|
48
|
+
'Apagar SOMENTE as próprias. A política única da 0049 deixava o DELETE alcançar a regra global, porque WITH CHECK não governa DELETE — só o USING governa.';
|
|
49
|
+
|
|
50
|
+
-- ── A mesma pergunta, feita às policies vizinhas ───────────────────────────
|
|
51
|
+
--
|
|
52
|
+
-- `role` e `role_permission` têm o mesmo formato desde a 0045 e, no papel,
|
|
53
|
+
-- o mesmo buraco no DELETE. Lá a segunda barreira segura: a 0045 revogou
|
|
54
|
+
-- INSERT, UPDATE e DELETE do runtime, e `migrate.ts` repete o REVOKE a cada
|
|
55
|
+
-- deploy. Fica registrado aqui porque a próxima pessoa a ler aquela policy vai
|
|
56
|
+
-- fazer esta pergunta — e a resposta é "o privilégio segura", não "a política
|
|
57
|
+
-- está certa".
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
-- 0053 — `valid_from` descreve a REGRA, não o dia em que a linha foi criada.
|
|
2
|
+
--
|
|
3
|
+
-- ═══ O erro da 0051, e por que ele parecia certo ═══════════════════════════
|
|
4
|
+
--
|
|
5
|
+
-- A 0051 gravou `valid_from = CURRENT_DATE` nas regras do seed, com a
|
|
6
|
+
-- justificativa de que é honesto dizer "esta regra existe no sistema desde
|
|
7
|
+
-- hoje". A frase é verdadeira e a modelagem estava errada: `valid_from` não
|
|
8
|
+
-- descreve quando o REGISTRO nasceu — descreve desde quando a REGRA vale.
|
|
9
|
+
--
|
|
10
|
+
-- O efeito apareceu no primeiro teste: um escritório que abre a competência de
|
|
11
|
+
-- agosto em setembro — que é o normal da profissão, não a exceção — não
|
|
12
|
+
-- recebia obrigação nenhuma, porque nenhuma regra era candidata para agosto.
|
|
13
|
+
--
|
|
14
|
+
-- ═══ Por que uma data antiga é mais honesta que hoje ══════════════════════
|
|
15
|
+
--
|
|
16
|
+
-- Não se sabe desde quando cada obrigação do seed está em vigor; várias são
|
|
17
|
+
-- anteriores ao produto. As duas opções eram:
|
|
18
|
+
--
|
|
19
|
+
-- hoje → afirma que a regra não valia em agosto. É falso.
|
|
20
|
+
-- limite baixo → afirma que ela vale desde antes de o sistema existir, sem
|
|
21
|
+
-- dizer desde quando. É verdadeiro e incompleto.
|
|
22
|
+
--
|
|
23
|
+
-- A segunda é a correta: `2000-01-01` aqui não é uma data legal, é a ausência
|
|
24
|
+
-- de início declarado. Declarar o início de verdade faz parte de validar a
|
|
25
|
+
-- regra, e as regras do seed continuam `pending_validation` justamente porque
|
|
26
|
+
-- ninguém as validou.
|
|
27
|
+
--
|
|
28
|
+
-- Nada disso relaxa a barreira: uma regra pendente não gera obrigação. O que
|
|
29
|
+
-- muda é que ela passa a ser CANDIDATA e a aparecer na prévia com o motivo
|
|
30
|
+
-- certo — "aguarda conferência" em vez de "não existe regra", que mandaria o
|
|
31
|
+
-- escritório procurar o que já está lá.
|
|
32
|
+
|
|
33
|
+
UPDATE fiscal_rule
|
|
34
|
+
SET valid_from = DATE '2000-01-01',
|
|
35
|
+
note = coalesce(note || ' ', '') ||
|
|
36
|
+
'[N1] Início de vigência não declarado: a data é um limite inferior, não uma afirmação legal.',
|
|
37
|
+
updated_at = now()
|
|
38
|
+
WHERE tenant_id IS NULL
|
|
39
|
+
AND deleted_at IS NULL
|
|
40
|
+
AND valid_from > DATE '2000-01-01'
|
|
41
|
+
AND status IN ('pending_validation', 'not_configured');
|
|
42
|
+
|
|
43
|
+
COMMENT ON COLUMN fiscal_rule.valid_from IS
|
|
44
|
+
'Desde quando a REGRA vale — não quando a linha foi criada. Regra sem início declarado usa um limite inferior antigo, e declarar o início real faz parte de validá-la.';
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
-- 0054 — a identidade do escritório vira dado do produto, e a regra fiscal
|
|
2
|
+
-- passa a citar a fonte.
|
|
3
|
+
--
|
|
4
|
+
-- ═══ Por que estas duas coisas na mesma migration ══════════════════════════
|
|
5
|
+
--
|
|
6
|
+
-- As duas nascem do mesmo achado da auditoria C360: o produto tinha caminho de
|
|
7
|
+
-- LEITURA e não tinha caminho de ESCRITA. A marca do escritório vivia em
|
|
8
|
+
-- `tenant.settings` e só era gravável por `UPDATE` manual no banco; a regra
|
|
9
|
+
-- fiscal tinha `source_reference` em texto livre e nenhum lugar canônico para o
|
|
10
|
+
-- endereço da norma. Nos dois casos o efeito é o mesmo: um escritório novo
|
|
11
|
+
-- exigia desenvolvedor.
|
|
12
|
+
--
|
|
13
|
+
-- Nenhuma tabela nova. Nenhum GRANT novo: `tenant` e `fiscal_rule` já estão na
|
|
14
|
+
-- allowlist do runtime, e GRANT em Postgres é por tabela — coluna nova nasce
|
|
15
|
+
-- alcançável pelo mesmo privilégio.
|
|
16
|
+
|
|
17
|
+
-- ── 1 · Identidade do escritório ───────────────────────────────────────────
|
|
18
|
+
--
|
|
19
|
+
-- `display_name` e `legal_name` já existiam. Faltavam o documento e o fuso, e
|
|
20
|
+
-- os dois têm consumidor concreto e próximo:
|
|
21
|
+
--
|
|
22
|
+
-- documento → o escritório é ele mesmo um contribuinte. A onda de ingestão
|
|
23
|
+
-- fiscal precisa do CNPJ dele para o certificado da própria casa
|
|
24
|
+
-- (`digital_certificate.client_id IS NULL` já prevê esse caso).
|
|
25
|
+
-- fuso → todo vencimento hoje é calculado em data, sem hora. No dia em
|
|
26
|
+
-- que houver corte por horário (janela de envio, D-0 às 18h), a
|
|
27
|
+
-- ausência do fuso vira erro de um dia para metade do país.
|
|
28
|
+
--
|
|
29
|
+
-- Só dígitos, como em `client.document_number`: máscara é apresentação, e duas
|
|
30
|
+
-- representações do mesmo documento não se encontram em nenhuma busca.
|
|
31
|
+
ALTER TABLE tenant ADD COLUMN IF NOT EXISTS document_number text;
|
|
32
|
+
ALTER TABLE tenant ADD COLUMN IF NOT EXISTS timezone text NOT NULL DEFAULT 'America/Sao_Paulo';
|
|
33
|
+
|
|
34
|
+
DO $$
|
|
35
|
+
BEGIN
|
|
36
|
+
IF NOT EXISTS (SELECT FROM pg_constraint WHERE conname = 'tenant_document_format') THEN
|
|
37
|
+
ALTER TABLE tenant ADD CONSTRAINT tenant_document_format
|
|
38
|
+
CHECK (document_number IS NULL OR document_number ~ '^[0-9]{11}$' OR document_number ~ '^[0-9]{14}$');
|
|
39
|
+
END IF;
|
|
40
|
+
|
|
41
|
+
-- Fuso: a lista dos fusos BRASILEIROS, não um texto livre.
|
|
42
|
+
--
|
|
43
|
+
-- `CHECK` não enxerga `pg_timezone_names`, então a alternativa seria aceitar
|
|
44
|
+
-- qualquer string e descobrir o erro na primeira conversão. O produto é
|
|
45
|
+
-- nacional; enumerar os dezesseis fusos do país é a restrição honesta e
|
|
46
|
+
-- fecha a porta para `'GMT-3'`, `'Brasilia'` e afins, que parecem certos e
|
|
47
|
+
-- não são identificadores IANA.
|
|
48
|
+
IF NOT EXISTS (SELECT FROM pg_constraint WHERE conname = 'tenant_timezone_br') THEN
|
|
49
|
+
ALTER TABLE tenant ADD CONSTRAINT tenant_timezone_br
|
|
50
|
+
CHECK (timezone IN (
|
|
51
|
+
'America/Sao_Paulo','America/Bahia','America/Fortaleza','America/Recife',
|
|
52
|
+
'America/Belem','America/Araguaina','America/Maceio','America/Campo_Grande',
|
|
53
|
+
'America/Cuiaba','America/Santarem','America/Manaus','America/Porto_Velho',
|
|
54
|
+
'America/Boa_Vista','America/Rio_Branco','America/Eirunepe','America/Noronha'
|
|
55
|
+
));
|
|
56
|
+
END IF;
|
|
57
|
+
END $$;
|
|
58
|
+
|
|
59
|
+
COMMENT ON COLUMN tenant.document_number IS
|
|
60
|
+
'CNPJ (14) ou CPF (11) do próprio escritório, só dígitos. O escritório é contribuinte de si mesmo — a ingestão fiscal precisa deste número para o certificado da casa.';
|
|
61
|
+
COMMENT ON COLUMN tenant.timezone IS
|
|
62
|
+
'Fuso IANA do escritório. Restrito aos fusos brasileiros: o produto é nacional e um texto livre aceitaria identificadores que não existem.';
|
|
63
|
+
|
|
64
|
+
-- ── 2 · A regra fiscal cita a fonte ────────────────────────────────────────
|
|
65
|
+
--
|
|
66
|
+
-- `source_reference` continua sendo a referência humana ("IN RFB 2.005/2021,
|
|
67
|
+
-- art. 3º"). `source_url` é o ENDEREÇO oficial, separado de propósito: uma URL
|
|
68
|
+
-- misturada com texto livre não pode ser verificada, aberta na tela nem
|
|
69
|
+
-- comparada entre versões.
|
|
70
|
+
--
|
|
71
|
+
-- Só https. A regra fiscal aparece numa tela de conferência e o endereço vira
|
|
72
|
+
-- link; `javascript:` e `data:` num campo editável seriam XSS armazenado com a
|
|
73
|
+
-- assinatura do escritório.
|
|
74
|
+
--
|
|
75
|
+
-- Isto NÃO valida a regra. Citar a fonte é o insumo da conferência humana, e
|
|
76
|
+
-- `status` continua exigindo `validated_by` e `validated_at` para sair de
|
|
77
|
+
-- `pending_validation`.
|
|
78
|
+
ALTER TABLE fiscal_rule ADD COLUMN IF NOT EXISTS source_url text;
|
|
79
|
+
|
|
80
|
+
DO $$
|
|
81
|
+
BEGIN
|
|
82
|
+
IF NOT EXISTS (SELECT FROM pg_constraint WHERE conname = 'fiscal_rule_source_url_https') THEN
|
|
83
|
+
ALTER TABLE fiscal_rule ADD CONSTRAINT fiscal_rule_source_url_https
|
|
84
|
+
CHECK (source_url IS NULL OR source_url ~ '^https://[^\s"''<>]+$');
|
|
85
|
+
END IF;
|
|
86
|
+
END $$;
|
|
87
|
+
|
|
88
|
+
COMMENT ON COLUMN fiscal_rule.source_url IS
|
|
89
|
+
'Endereço oficial da norma, https. Insumo da conferência humana — citar a fonte não valida a regra.';
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
-- 0055 — o contrato de capacidade dos JOBS, e a elegibilidade fiscal default-deny.
|
|
2
|
+
--
|
|
3
|
+
-- ═══ O que a Onda A fechou, e o que ficou aberto ═══════════════════════════
|
|
4
|
+
--
|
|
5
|
+
-- A Onda A fechou o skew de release entre a tela e a API: `GET /v1/capabilities`
|
|
6
|
+
-- declara o que aquele build serve, o console exige o que vai usar, e a
|
|
7
|
+
-- requisição condenada não parte (0054 / docs/architecture/141).
|
|
8
|
+
--
|
|
9
|
+
-- Isso protege a superfície HTTP. Não protege NADA que roda sem navegador.
|
|
10
|
+
--
|
|
11
|
+
-- Os dois crons deste produto (`baruk-collection-cron`, `baruk-billing-cron`)
|
|
12
|
+
-- publicam na Render como serviços SEPARADOS do serviço web, a partir da mesma
|
|
13
|
+
-- imagem mas com deploys independentes — e as migrations rodam no
|
|
14
|
+
-- `preDeployCommand` do serviço WEB, não no cron. A ordem entre "a imagem nova
|
|
15
|
+
-- do cron subiu" e "o schema novo foi aplicado" não é garantida por nada.
|
|
16
|
+
--
|
|
17
|
+
-- Então existem os dois lados da janela:
|
|
18
|
+
--
|
|
19
|
+
-- worker NOVO + schema VELHO → o job depende de coluna/tabela que ainda não
|
|
20
|
+
-- existe. Hoje isso aparece como exceção no meio do loop, DEPOIS de já ter
|
|
21
|
+
-- escrito no tenant anterior — estado parcial, que é exatamente o que a
|
|
22
|
+
-- ingestão fiscal não pode produzir.
|
|
23
|
+
--
|
|
24
|
+
-- worker VELHO + schema NOVO → o job escreve linhas sem o que o schema novo
|
|
25
|
+
-- passou a esperar. Aditivo sobrevive; obrigatório não.
|
|
26
|
+
--
|
|
27
|
+
-- ═══ Por que capacidade, e não SHA — de novo, e por outro motivo ═══════════
|
|
28
|
+
--
|
|
29
|
+
-- Para a tela, a contraparte é a API. Para um worker, a contraparte é o BANCO:
|
|
30
|
+
-- é a única superfície que os dois lados enxergam. Comparar o commit da imagem
|
|
31
|
+
-- do cron com o commit do serviço web acoplaria o job ao processo de release e
|
|
32
|
+
-- reprovaria um hotfix inofensivo.
|
|
33
|
+
--
|
|
34
|
+
-- Por isso o registro vive AQUI, no banco, e quem o escreve é a MIGRATION —
|
|
35
|
+
-- isto é, o mesmo ato que cria a capacidade. Uma capacidade não pode ser
|
|
36
|
+
-- declarada por quem a consome: `baruk_app` recebe apenas SELECT nesta tabela
|
|
37
|
+
-- (ver `db/migrate.ts`). Autoridade escrita pelo controlado não é autoridade,
|
|
38
|
+
-- e um worker que pudesse declarar a própria capacidade teria um portão com a
|
|
39
|
+
-- chave do lado de dentro.
|
|
40
|
+
|
|
41
|
+
-- ── 1 · Registro de capacidades da PLATAFORMA ──────────────────────────────
|
|
42
|
+
--
|
|
43
|
+
-- Global, sem `tenant_id`: a capacidade é do schema, não do escritório. Sem RLS
|
|
44
|
+
-- pelo mesmo motivo que `fiscal_attribute_definition` — e, como lá, a proteção
|
|
45
|
+
-- é o privilégio, não a policy.
|
|
46
|
+
--
|
|
47
|
+
-- Chave IMUTÁVEL, igual ao contrato HTTP: mudança incompatível ganha `.v2`, e a
|
|
48
|
+
-- `.v1` só sai quando nenhum worker em produção ainda a exigir. É essa regra
|
|
49
|
+
-- que faz `worker velho + schema novo` ser seguro: o registro só CRESCE, e
|
|
50
|
+
-- compatibilidade é continência de conjunto.
|
|
51
|
+
CREATE TABLE IF NOT EXISTS platform_capability (
|
|
52
|
+
key text PRIMARY KEY,
|
|
53
|
+
label text NOT NULL,
|
|
54
|
+
-- Versão do FORMATO do contrato, não da capacidade. Um worker que não
|
|
55
|
+
-- reconhece a versão trata tudo como indisponível: fail-closed é a única
|
|
56
|
+
-- leitura segura de um contrato que não se sabe ler.
|
|
57
|
+
contract_version int NOT NULL,
|
|
58
|
+
-- Qual migration declarou. Não é decoração: é como se responde "desde qual
|
|
59
|
+
-- deploy esta capacidade existe?" sem depender de git em tempo de execução.
|
|
60
|
+
declared_by_migration text NOT NULL,
|
|
61
|
+
declared_at timestamptz NOT NULL DEFAULT now(),
|
|
62
|
+
CONSTRAINT platform_capability_key_format
|
|
63
|
+
CHECK (key ~ '^[a-z0-9]+(-[a-z0-9]+)*(\.[a-z0-9]+(-[a-z0-9]+)*)+\.v[0-9]+$')
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
COMMENT ON TABLE platform_capability IS
|
|
67
|
+
'O que ESTE schema sabe fazer. Escrito só por migration (baruk_app tem apenas SELECT): quem consome a capacidade não pode declará-la.';
|
|
68
|
+
|
|
69
|
+
INSERT INTO platform_capability (key, label, contract_version, declared_by_migration) VALUES
|
|
70
|
+
('office.job-contract.v1',
|
|
71
|
+
'Contrato de capacidade para jobs e workers', 1, '0055'),
|
|
72
|
+
('office.collection-cycle.v1',
|
|
73
|
+
'Ciclo diário de cobrança: geração de recebíveis da competência + régua', 1, '0055'),
|
|
74
|
+
('office.saas-billing-cycle.v1',
|
|
75
|
+
'Ciclo do Billing SaaS: trial, renovação, régua e suspensão', 1, '0055')
|
|
76
|
+
ON CONFLICT (key) DO NOTHING;
|
|
77
|
+
|
|
78
|
+
-- ── 2 · Cursor do job, por tenant ──────────────────────────────────────────
|
|
79
|
+
--
|
|
80
|
+
-- Existe para que "não consumir cursor irreversivelmente" seja uma propriedade
|
|
81
|
+
-- verificável, e não uma promessa. O cursor só avança quando o lote INTEIRO
|
|
82
|
+
-- termina sob um contrato compatível; run bloqueado não o toca.
|
|
83
|
+
--
|
|
84
|
+
-- `contract_version` grava sob qual contrato aquela posição foi alcançada. Um
|
|
85
|
+
-- worker que leia um cursor gravado sob contrato que ele não reconhece PARA —
|
|
86
|
+
-- em vez de reinterpretar a posição com semântica diferente.
|
|
87
|
+
CREATE TABLE IF NOT EXISTS job_cursor (
|
|
88
|
+
id uuid PRIMARY KEY,
|
|
89
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
90
|
+
job_name text NOT NULL,
|
|
91
|
+
position text NOT NULL,
|
|
92
|
+
contract_version int NOT NULL,
|
|
93
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
94
|
+
CONSTRAINT job_cursor_tenant_id_uq UNIQUE (tenant_id, id)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
CREATE UNIQUE INDEX IF NOT EXISTS job_cursor_uq ON job_cursor (tenant_id, job_name);
|
|
98
|
+
|
|
99
|
+
ALTER TABLE job_cursor ENABLE ROW LEVEL SECURITY;
|
|
100
|
+
ALTER TABLE job_cursor FORCE ROW LEVEL SECURITY;
|
|
101
|
+
CREATE POLICY job_cursor_tenant_isolation ON job_cursor
|
|
102
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
103
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
104
|
+
|
|
105
|
+
-- ── 3 · Trilha de execução do job ──────────────────────────────────────────
|
|
106
|
+
--
|
|
107
|
+
-- Um job bloqueado por incompatibilidade não pode falhar em silêncio. Esta
|
|
108
|
+
-- tabela é o registro nomeado do bloqueio: qual job, qual versão, o que exigia,
|
|
109
|
+
-- o que o schema declarava, e quando.
|
|
110
|
+
--
|
|
111
|
+
-- Sem PII e sem segredo por construção: só nomes de capacidade e contadores.
|
|
112
|
+
CREATE TABLE IF NOT EXISTS job_run (
|
|
113
|
+
id uuid PRIMARY KEY,
|
|
114
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
115
|
+
job_name text NOT NULL,
|
|
116
|
+
job_version int NOT NULL,
|
|
117
|
+
-- Os cinco estados. `TEMPORARILY_UNAVAILABLE` é deliberadamente separado de
|
|
118
|
+
-- `INCOMPATIBLE`: o primeiro volta sozinho e merece retry; o segundo exige um
|
|
119
|
+
-- deploy, e insistir nele é gastar orçamento contra uma parede.
|
|
120
|
+
readiness text NOT NULL CHECK (readiness IN (
|
|
121
|
+
'READY', 'TEMPORARILY_UNAVAILABLE', 'INCOMPATIBLE',
|
|
122
|
+
'DISABLED', 'BLOCKED_BY_TENANT_CONFIG')),
|
|
123
|
+
status text NOT NULL CHECK (status IN ('completed', 'blocked', 'failed')),
|
|
124
|
+
contract_version int,
|
|
125
|
+
required_capabilities text[] NOT NULL DEFAULT '{}',
|
|
126
|
+
observed_capabilities text[] NOT NULL DEFAULT '{}',
|
|
127
|
+
missing_capabilities text[] NOT NULL DEFAULT '{}',
|
|
128
|
+
mutations int NOT NULL DEFAULT 0 CHECK (mutations >= 0),
|
|
129
|
+
cursor_advanced boolean NOT NULL DEFAULT false,
|
|
130
|
+
detail text,
|
|
131
|
+
started_at timestamptz NOT NULL DEFAULT now(),
|
|
132
|
+
finished_at timestamptz,
|
|
133
|
+
CONSTRAINT job_run_tenant_id_uq UNIQUE (tenant_id, id),
|
|
134
|
+
-- O fail-closed vira invariante do BANCO, não promessa do TypeScript: é
|
|
135
|
+
-- impossível registrar um run bloqueado que tenha mutado ou avançado cursor.
|
|
136
|
+
-- Um refactor futuro que erre a ordem das operações não passa daqui.
|
|
137
|
+
CONSTRAINT job_run_blocked_is_inert
|
|
138
|
+
CHECK (status <> 'blocked' OR (mutations = 0 AND cursor_advanced = false)),
|
|
139
|
+
-- `READY` e bloqueio são mutuamente exclusivos: um run bloqueado tem de dizer
|
|
140
|
+
-- POR QUE, e 'READY' não é um motivo.
|
|
141
|
+
CONSTRAINT job_run_blocked_has_reason
|
|
142
|
+
CHECK (status <> 'blocked' OR readiness <> 'READY')
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
CREATE INDEX IF NOT EXISTS job_run_tenant_job_idx
|
|
146
|
+
ON job_run (tenant_id, job_name, started_at DESC);
|
|
147
|
+
|
|
148
|
+
ALTER TABLE job_run ENABLE ROW LEVEL SECURITY;
|
|
149
|
+
ALTER TABLE job_run FORCE ROW LEVEL SECURITY;
|
|
150
|
+
CREATE POLICY job_run_tenant_isolation ON job_run
|
|
151
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
152
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
153
|
+
|
|
154
|
+
COMMENT ON CONSTRAINT job_run_blocked_is_inert ON job_run IS
|
|
155
|
+
'Fail-closed como invariante de banco: run bloqueado com mutação ou cursor avançado não é gravável.';
|
|
156
|
+
|
|
157
|
+
-- ═══ 4 · Elegibilidade fiscal — default deny em três camadas ════════════════
|
|
158
|
+
--
|
|
159
|
+
-- O achado que motiva isto: hoje NADA no produto distingue "cliente que existe"
|
|
160
|
+
-- de "cliente que pode entrar em automação fiscal". Um job futuro que
|
|
161
|
+
-- selecionasse por `deleted_at IS NULL` alcançaria, no tenant da SC, dois
|
|
162
|
+
-- cadastros que foram criados em teste — e alcançaria a carteira real inteira
|
|
163
|
+
-- no dia seguinte a uma importação.
|
|
164
|
+
--
|
|
165
|
+
-- É a mesma lição da 0047 (liberação do destinatário), aplicada a documento
|
|
166
|
+
-- fiscal em vez de e-mail: a ausência tem de ser a barreira. Um default "entra
|
|
167
|
+
-- quem ninguém proibiu" transforma omissão em autorização — e omissão é o
|
|
168
|
+
-- estado natural de todo cliente que acabou de entrar.
|
|
169
|
+
--
|
|
170
|
+
-- Três camadas, porque três coisas diferentes podem estar erradas:
|
|
171
|
+
-- tenant → o ESCRITÓRIO ligou automação fiscal? em qual ambiente?
|
|
172
|
+
-- cliente → ESTE cliente foi inscrito, para ESTE tipo de documento?
|
|
173
|
+
-- credencial → existe insumo para operar em nome dele? verificado?
|
|
174
|
+
--
|
|
175
|
+
-- E uma quarta, que não é tabela: o estado de operação real
|
|
176
|
+
-- (`tenant_pilot_milestone.real_pilot_start`, 0047). Ambiente `production`
|
|
177
|
+
-- exige o marco declarado; `synthetic` não — é o que mantém desenvolvimento e
|
|
178
|
+
-- homologação possíveis sem abrir a porta da carteira real.
|
|
179
|
+
|
|
180
|
+
-- ── 4.1 · O escritório liga a automação, e declara em qual ambiente ────────
|
|
181
|
+
--
|
|
182
|
+
-- Ausência de linha = `disabled`. Não existe valor que signifique "herda".
|
|
183
|
+
--
|
|
184
|
+
-- `mode` é ambiente E chave ao mesmo tempo, de propósito: separá-los criaria o
|
|
185
|
+
-- estado `enabled=true, environment=null`, que alguém teria de interpretar — e
|
|
186
|
+
-- interpretação é onde documento de homologação vira documento real.
|
|
187
|
+
CREATE TABLE IF NOT EXISTS tenant_fiscal_automation (
|
|
188
|
+
tenant_id uuid PRIMARY KEY REFERENCES tenant(id),
|
|
189
|
+
mode text NOT NULL DEFAULT 'disabled'
|
|
190
|
+
CHECK (mode IN ('disabled', 'synthetic', 'production')),
|
|
191
|
+
enabled_at timestamptz,
|
|
192
|
+
enabled_by uuid REFERENCES "user"(id),
|
|
193
|
+
note text,
|
|
194
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
195
|
+
-- Ligar exige autor e data: "quem ligou isto?" é a única pergunta que a
|
|
196
|
+
-- linha existe para responder, e ela não pode ficar sem resposta.
|
|
197
|
+
CONSTRAINT tenant_fiscal_automation_enable_coherent
|
|
198
|
+
CHECK (mode = 'disabled' OR (enabled_at IS NOT NULL AND enabled_by IS NOT NULL))
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
ALTER TABLE tenant_fiscal_automation ENABLE ROW LEVEL SECURITY;
|
|
202
|
+
ALTER TABLE tenant_fiscal_automation FORCE ROW LEVEL SECURITY;
|
|
203
|
+
CREATE POLICY tenant_fiscal_automation_tenant_isolation ON tenant_fiscal_automation
|
|
204
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
205
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
206
|
+
|
|
207
|
+
COMMENT ON TABLE tenant_fiscal_automation IS
|
|
208
|
+
'Ausência de linha = automação fiscal desligada. Nenhuma migration liga escritório nenhum; ligar é ato humano com autor e data.';
|
|
209
|
+
|
|
210
|
+
-- ── 4.2 · A inscrição do cliente, por tipo de documento ────────────────────
|
|
211
|
+
--
|
|
212
|
+
-- Por TIPO, e não um booleano no cliente: um escritório pode acompanhar a NFS-e
|
|
213
|
+
-- de um cliente sem tocar na NF-e dele, e o inverso. Um booleano forçaria tudo
|
|
214
|
+
-- ou nada, e "tudo" é sempre a escolha errada quando o insumo é documento
|
|
215
|
+
-- fiscal de terceiro.
|
|
216
|
+
--
|
|
217
|
+
-- Revogação é lógica e mantém o histórico: quem esteve inscrito e saiu é um
|
|
218
|
+
-- fato que a trilha precisa preservar.
|
|
219
|
+
CREATE TABLE IF NOT EXISTS client_fiscal_enrollment (
|
|
220
|
+
id uuid PRIMARY KEY,
|
|
221
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
222
|
+
client_id uuid NOT NULL,
|
|
223
|
+
document_type text NOT NULL CHECK (document_type IN ('nfe', 'nfse', 'cte', 'nfce')),
|
|
224
|
+
enrolled_at timestamptz NOT NULL DEFAULT now(),
|
|
225
|
+
enrolled_by uuid REFERENCES "user"(id),
|
|
226
|
+
revoked_at timestamptz,
|
|
227
|
+
revoked_by uuid REFERENCES "user"(id),
|
|
228
|
+
note text,
|
|
229
|
+
CONSTRAINT client_fiscal_enrollment_tenant_id_uq UNIQUE (tenant_id, id),
|
|
230
|
+
FOREIGN KEY (tenant_id, client_id) REFERENCES client (tenant_id, id),
|
|
231
|
+
CONSTRAINT client_fiscal_enrollment_revoke_coherent
|
|
232
|
+
CHECK ((revoked_at IS NULL) = (revoked_by IS NULL))
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
-- Uma inscrição VIVA por (cliente, tipo). Revogadas coexistem: são histórico.
|
|
236
|
+
CREATE UNIQUE INDEX IF NOT EXISTS client_fiscal_enrollment_live_uq
|
|
237
|
+
ON client_fiscal_enrollment (tenant_id, client_id, document_type)
|
|
238
|
+
WHERE revoked_at IS NULL;
|
|
239
|
+
|
|
240
|
+
ALTER TABLE client_fiscal_enrollment ENABLE ROW LEVEL SECURITY;
|
|
241
|
+
ALTER TABLE client_fiscal_enrollment FORCE ROW LEVEL SECURITY;
|
|
242
|
+
CREATE POLICY client_fiscal_enrollment_tenant_isolation ON client_fiscal_enrollment
|
|
243
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
244
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
245
|
+
|
|
246
|
+
-- ── 4.3 · Prontidão da credencial ──────────────────────────────────────────
|
|
247
|
+
--
|
|
248
|
+
-- Esta fase NÃO exige certificado A1. Ela define o conceito e o lugar.
|
|
249
|
+
--
|
|
250
|
+
-- O estado `no_credential` não está no CHECK de propósito: ele é a AUSÊNCIA de
|
|
251
|
+
-- linha, como em `client.communication_cleared_at`. Um enum com `no_credential`
|
|
252
|
+
-- permitiria a linha existir dizendo "não tem" — e daí alguém a criaria por
|
|
253
|
+
-- conveniência, e "não tem" viraria um estado configurável em vez do estado
|
|
254
|
+
-- natural de todo cliente.
|
|
255
|
+
--
|
|
256
|
+
-- `secret_ref` é referência do cofre (`vault://<nome>`), nunca o segredo. O
|
|
257
|
+
-- certificado é do CLIENTE, não do escritório e nem nosso: o que guardamos é
|
|
258
|
+
-- para onde apontar.
|
|
259
|
+
CREATE TABLE IF NOT EXISTS client_fiscal_credential (
|
|
260
|
+
id uuid PRIMARY KEY,
|
|
261
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
262
|
+
client_id uuid NOT NULL,
|
|
263
|
+
kind text NOT NULL CHECK (kind IN ('certificate_a1', 'municipal_portal')),
|
|
264
|
+
status text NOT NULL
|
|
265
|
+
CHECK (status IN ('configured_not_verified', 'verified', 'expired', 'revoked')),
|
|
266
|
+
secret_ref text,
|
|
267
|
+
verified_at timestamptz,
|
|
268
|
+
expires_on date,
|
|
269
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
270
|
+
CONSTRAINT client_fiscal_credential_tenant_id_uq UNIQUE (tenant_id, id),
|
|
271
|
+
FOREIGN KEY (tenant_id, client_id) REFERENCES client (tenant_id, id),
|
|
272
|
+
-- `verified` sem data de verificação é uma afirmação sem prova.
|
|
273
|
+
CONSTRAINT client_fiscal_credential_verified_coherent
|
|
274
|
+
CHECK (status <> 'verified' OR verified_at IS NOT NULL),
|
|
275
|
+
-- Referência do cofre, jamais material. Um `-----BEGIN` aqui é acidente
|
|
276
|
+
-- grave; o banco recusa antes de virar um vazamento em backup.
|
|
277
|
+
CONSTRAINT client_fiscal_credential_ref_is_reference
|
|
278
|
+
CHECK (secret_ref IS NULL OR secret_ref ~ '^vault://[A-Za-z0-9_.:-]+$')
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
CREATE UNIQUE INDEX IF NOT EXISTS client_fiscal_credential_uq
|
|
282
|
+
ON client_fiscal_credential (tenant_id, client_id, kind);
|
|
283
|
+
|
|
284
|
+
ALTER TABLE client_fiscal_credential ENABLE ROW LEVEL SECURITY;
|
|
285
|
+
ALTER TABLE client_fiscal_credential FORCE ROW LEVEL SECURITY;
|
|
286
|
+
CREATE POLICY client_fiscal_credential_tenant_isolation ON client_fiscal_credential
|
|
287
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
288
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
289
|
+
|
|
290
|
+
COMMENT ON COLUMN client_fiscal_credential.secret_ref IS
|
|
291
|
+
'Referência do cofre (vault://…). NUNCA o certificado nem a senha dele — o material é do cliente e não passa por aqui.';
|
|
292
|
+
|
|
293
|
+
-- ── 5 · Nenhum cliente existente nasce elegível ────────────────────────────
|
|
294
|
+
--
|
|
295
|
+
-- Não há UPDATE, INSERT ou backfill nesta migration que torne alguém elegível.
|
|
296
|
+
-- É a afirmação central do gate e ela é verificável: as três tabelas acima
|
|
297
|
+
-- nascem VAZIAS, e vazio significa negado nas três camadas.
|
|
298
|
+
--
|
|
299
|
+
-- Vale para os 13 registros da SC e para os tenants sintéticos de certificação
|
|
300
|
+
-- pelo mesmo motivo — nenhum deles é mencionado, então nenhum deles é ligado.
|