@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,321 @@
|
|
|
1
|
+
-- 0060 — o cofre fiscal ganha classe de exposição, o certificado ganha
|
|
2
|
+
-- identidade, e a primeira consulta real ganha um portão que se consome.
|
|
3
|
+
--
|
|
4
|
+
-- ═══ O defeito que a primeira seção existe para tornar indizível ══════════
|
|
5
|
+
--
|
|
6
|
+
-- `vault_credential` (0012) guarda todo segredo do escritório sob uma única
|
|
7
|
+
-- regra de leitura: quem tem `vault.credential.decrypt` chama
|
|
8
|
+
-- `POST /v1/vault/credentials/:id/reveal` e recebe o texto em claro. Para uma
|
|
9
|
+
-- chave de API isso é o comportamento desejado — o operador precisa colá-la
|
|
10
|
+
-- noutro sistema.
|
|
11
|
+
--
|
|
12
|
+
-- Para o material de um certificado digital, é a porta dos fundos do cofre. O
|
|
13
|
+
-- envelope que a Fase 2 definiu carrega a CHAVE PRIVADA do cliente em base64;
|
|
14
|
+
-- revelá-lo numa tela é entregá-la, e "não faça isso" não é um controle. Pior:
|
|
15
|
+
-- o papel `accountant` do catálogo já carrega `vault.credential.decrypt`, de
|
|
16
|
+
-- modo que a porta estava aberta para todo contador do escritório.
|
|
17
|
+
--
|
|
18
|
+
-- A correção não é tirar o botão da tela. É dizer no BANCO que existem duas
|
|
19
|
+
-- classes de segredo, e que a segunda não tem caminho de saída:
|
|
20
|
+
--
|
|
21
|
+
-- revealable pode voltar ao humano que o guardou (chave de API, token).
|
|
22
|
+
-- write_only entra, é usado pelo processo, e NUNCA volta.
|
|
23
|
+
--
|
|
24
|
+
-- E é uma RESTRIÇÃO, não uma convenção, que amarra `certificate` à segunda: um
|
|
25
|
+
-- certificado gravado por qualquer caminho — rota nova, script, seed — nasce
|
|
26
|
+
-- irrecuperável, inclusive num caminho que ainda não foi escrito.
|
|
27
|
+
|
|
28
|
+
ALTER TABLE vault_credential ADD COLUMN IF NOT EXISTS exposure text NOT NULL DEFAULT 'revealable';
|
|
29
|
+
|
|
30
|
+
DO $$
|
|
31
|
+
BEGIN
|
|
32
|
+
IF NOT EXISTS (SELECT FROM pg_constraint WHERE conname = 'vault_credential_exposure_values') THEN
|
|
33
|
+
ALTER TABLE vault_credential ADD CONSTRAINT vault_credential_exposure_values
|
|
34
|
+
CHECK (exposure IN ('revealable', 'write_only'));
|
|
35
|
+
END IF;
|
|
36
|
+
END $$;
|
|
37
|
+
|
|
38
|
+
-- Backfill ANTES da restrição de coerência: uma credencial de certificado já
|
|
39
|
+
-- gravada sob a regra antiga tornaria o CHECK inválido, e um `NOT VALID`
|
|
40
|
+
-- silencioso deixaria exatamente as linhas antigas — as que já correram risco —
|
|
41
|
+
-- fora da garantia.
|
|
42
|
+
UPDATE vault_credential SET exposure = 'write_only'
|
|
43
|
+
WHERE category = 'certificate' AND exposure <> 'write_only';
|
|
44
|
+
|
|
45
|
+
DO $$
|
|
46
|
+
BEGIN
|
|
47
|
+
IF NOT EXISTS (SELECT FROM pg_constraint WHERE conname = 'vault_credential_certificate_is_write_only') THEN
|
|
48
|
+
ALTER TABLE vault_credential ADD CONSTRAINT vault_credential_certificate_is_write_only
|
|
49
|
+
CHECK (category <> 'certificate' OR exposure = 'write_only');
|
|
50
|
+
END IF;
|
|
51
|
+
END $$;
|
|
52
|
+
|
|
53
|
+
COMMENT ON COLUMN vault_credential.exposure IS
|
|
54
|
+
'write_only = não existe caminho de leitura para humano, por nenhuma rota. Material de certificado é write_only por RESTRIÇÃO, não por disciplina da camada de rota.';
|
|
55
|
+
COMMENT ON CONSTRAINT vault_credential_certificate_is_write_only ON vault_credential IS
|
|
56
|
+
'Remover esta restrição é a decisão consciente de permitir que a chave privada de um cliente volte para uma tela.';
|
|
57
|
+
|
|
58
|
+
-- ═══ 2 · A autorização de execução única ═════════════════════════════════
|
|
59
|
+
--
|
|
60
|
+
-- O motor da Fase 2 tem três desligamentos (flag de ambiente, elegibilidade,
|
|
61
|
+
-- cadência) e todos são ESTADO: ligados, ficam ligados. Para a primeira
|
|
62
|
+
-- consulta real contra um ambiente oficial, em nome de um contribuinte que não
|
|
63
|
+
-- pediu nada, estado permanente é a forma errada de autorização — o titular
|
|
64
|
+
-- autorizou UMA leitura, não um regime.
|
|
65
|
+
--
|
|
66
|
+
-- Esta tabela é um portão que se gasta. Quatro propriedades, todas no schema:
|
|
67
|
+
--
|
|
68
|
+
-- `max_runs = 1` CHECK literal. "Uma execução" não é configuração.
|
|
69
|
+
-- `operation = 'READ_ONLY'` idem. Mutação é INGRAVÁVEL nesta fase.
|
|
70
|
+
-- `expires_at` uma autorização esquecida morre sozinha.
|
|
71
|
+
-- `runs_consumed` nunca ultrapassa `max_runs`, e o CHECK é quem diz.
|
|
72
|
+
--
|
|
73
|
+
-- O período vem por EXTENSO — `period_start` e `period_end` além do par
|
|
74
|
+
-- ano/mês. O relato humano que originou esta frente continha exemplos de datas
|
|
75
|
+
-- inconsistentes entre si, e transformar "mês anterior" em regra implícita
|
|
76
|
+
-- produziria uma coleta cuja janela ninguém confirmou. Aqui a janela é dado
|
|
77
|
+
-- gravado, e a tela mostra as duas datas antes de qualquer execução.
|
|
78
|
+
CREATE TABLE IF NOT EXISTS fiscal_run_authorization (
|
|
79
|
+
id uuid PRIMARY KEY,
|
|
80
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
81
|
+
client_id uuid NOT NULL,
|
|
82
|
+
|
|
83
|
+
document_type text NOT NULL CHECK (document_type IN ('nfse', 'nfe', 'cte', 'nfce')),
|
|
84
|
+
environment text NOT NULL CHECK (environment IN ('synthetic', 'homologation', 'production')),
|
|
85
|
+
-- Slug da fonte, o mesmo vocabulário que governa cursor, disjuntor e
|
|
86
|
+
-- prontidão (`fiscal_sync_cursor.source`). Uma autorização emitida para uma
|
|
87
|
+
-- fonte não vale para outra.
|
|
88
|
+
source text NOT NULL,
|
|
89
|
+
credential_kind text NOT NULL DEFAULT 'certificate_a1'
|
|
90
|
+
CHECK (credential_kind IN ('certificate_a1', 'certificate_a3', 'municipal_portal')),
|
|
91
|
+
|
|
92
|
+
operation text NOT NULL DEFAULT 'READ_ONLY' CHECK (operation IN ('READ_ONLY', 'MUTATING')),
|
|
93
|
+
|
|
94
|
+
competence_year int NOT NULL CHECK (competence_year BETWEEN 2000 AND 2100),
|
|
95
|
+
competence_month int NOT NULL CHECK (competence_month BETWEEN 1 AND 12),
|
|
96
|
+
period_start date NOT NULL,
|
|
97
|
+
period_end date NOT NULL,
|
|
98
|
+
|
|
99
|
+
max_runs int NOT NULL DEFAULT 1,
|
|
100
|
+
runs_consumed int NOT NULL DEFAULT 0,
|
|
101
|
+
|
|
102
|
+
authorized_by uuid NOT NULL REFERENCES "user"(id),
|
|
103
|
+
authorized_at timestamptz NOT NULL DEFAULT now(),
|
|
104
|
+
-- Responsável contábil DECLARADO para esta execução. Texto, e não FK para
|
|
105
|
+
-- `user`: o profissional responsável pode não ter login no produto, e exigir
|
|
106
|
+
-- que tivesse forçaria a criação de uma identidade que ninguém pediu.
|
|
107
|
+
responsible_name text,
|
|
108
|
+
expires_at timestamptz NOT NULL,
|
|
109
|
+
|
|
110
|
+
consumed_at timestamptz,
|
|
111
|
+
consumed_by_run_id uuid,
|
|
112
|
+
revoked_at timestamptz,
|
|
113
|
+
revoked_by uuid REFERENCES "user"(id),
|
|
114
|
+
revoke_reason text,
|
|
115
|
+
|
|
116
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
117
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
118
|
+
|
|
119
|
+
CONSTRAINT fiscal_run_authorization_tenant_id_uq UNIQUE (tenant_id, id),
|
|
120
|
+
FOREIGN KEY (tenant_id, client_id) REFERENCES client (tenant_id, id),
|
|
121
|
+
|
|
122
|
+
CONSTRAINT fiscal_run_authorization_one_shot CHECK (max_runs = 1),
|
|
123
|
+
CONSTRAINT fiscal_run_authorization_read_only CHECK (operation = 'READ_ONLY'),
|
|
124
|
+
CONSTRAINT fiscal_run_authorization_budget CHECK (runs_consumed >= 0 AND runs_consumed <= max_runs),
|
|
125
|
+
CONSTRAINT fiscal_run_authorization_consumption_coherent
|
|
126
|
+
CHECK ((consumed_at IS NULL) = (runs_consumed = 0)),
|
|
127
|
+
CONSTRAINT fiscal_run_authorization_window CHECK (period_end >= period_start),
|
|
128
|
+
CONSTRAINT fiscal_run_authorization_expiry CHECK (expires_at > authorized_at),
|
|
129
|
+
CONSTRAINT fiscal_run_authorization_revocation_coherent
|
|
130
|
+
CHECK ((revoked_at IS NULL) = (revoked_by IS NULL))
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
COMMENT ON CONSTRAINT fiscal_run_authorization_one_shot ON fiscal_run_authorization IS
|
|
134
|
+
'Uma execução. Não é configuração: é restrição. Um segundo run real exige uma segunda autorização.';
|
|
135
|
+
COMMENT ON CONSTRAINT fiscal_run_authorization_read_only ON fiscal_run_authorization IS
|
|
136
|
+
'Mutação em sistema fiscal externo é ingravável nesta fase. Remover esta restrição é a decisão consciente de permitir escrita.';
|
|
137
|
+
|
|
138
|
+
-- Uma autorização VIVA por (cliente, fonte, ambiente, competência). Sem isto,
|
|
139
|
+
-- emitir duas e consumir as duas devolve na prática o regime permanente que a
|
|
140
|
+
-- tabela existe para impedir.
|
|
141
|
+
CREATE UNIQUE INDEX IF NOT EXISTS fiscal_run_authorization_live_uq
|
|
142
|
+
ON fiscal_run_authorization (tenant_id, client_id, source, environment,
|
|
143
|
+
competence_year, competence_month)
|
|
144
|
+
WHERE consumed_at IS NULL AND revoked_at IS NULL;
|
|
145
|
+
|
|
146
|
+
CREATE INDEX IF NOT EXISTS fiscal_run_authorization_client_idx
|
|
147
|
+
ON fiscal_run_authorization (tenant_id, client_id, authorized_at DESC);
|
|
148
|
+
|
|
149
|
+
ALTER TABLE fiscal_run_authorization ENABLE ROW LEVEL SECURITY;
|
|
150
|
+
ALTER TABLE fiscal_run_authorization FORCE ROW LEVEL SECURITY;
|
|
151
|
+
CREATE POLICY fiscal_run_authorization_tenant_isolation ON fiscal_run_authorization
|
|
152
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
153
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
154
|
+
|
|
155
|
+
-- ═══ 3 · A cobrança da PLATAFORMA, separada da cobrança do escritório ═════
|
|
156
|
+
--
|
|
157
|
+
-- Há duas cobranças neste produto e confundi-las custa caro nas duas direções:
|
|
158
|
+
--
|
|
159
|
+
-- plataforma Baruk → escritório (assinatura do Office). `saas_subscription`.
|
|
160
|
+
-- escritório escritório → clientes dele (honorários). `receivable`.
|
|
161
|
+
--
|
|
162
|
+
-- O escritório fundador não paga a primeira. A forma ERRADA de implementar isso
|
|
163
|
+
-- é desligar o financeiro dele — que apagaria a segunda, que é o produto
|
|
164
|
+
-- inteiro. A forma errada seguinte é `if (tenant.code === 'sc')`, que faz o
|
|
165
|
+
-- segundo escritório fundador virar um deploy.
|
|
166
|
+
--
|
|
167
|
+
-- Esta tabela é a forma certa: um fato do tenant, com quem concedeu, quando, e
|
|
168
|
+
-- por quê. O motor de billing lê a linha; ele não conhece nenhum código de
|
|
169
|
+
-- escritório.
|
|
170
|
+
--
|
|
171
|
+
-- ═══ Quem escreve não é quem é cobrado ═══════════════════════════════════
|
|
172
|
+
--
|
|
173
|
+
-- Um controle escrito pelo controlado não é controle. Se o tenant pudesse
|
|
174
|
+
-- gravar a própria isenção, todo escritório seria fundador na primeira tarde.
|
|
175
|
+
-- As políticas abaixo são POR COMANDO: o tenant LÊ a própria linha; só o
|
|
176
|
+
-- operador da plataforma (a GUC `app.platform_operator`, que apenas as rotas de
|
|
177
|
+
-- backoffice setam) INSERE, ATUALIZA ou APAGA.
|
|
178
|
+
CREATE TABLE IF NOT EXISTS tenant_platform_billing (
|
|
179
|
+
tenant_id uuid PRIMARY KEY REFERENCES tenant(id),
|
|
180
|
+
billing_mode text NOT NULL DEFAULT 'standard' CHECK (billing_mode IN ('standard', 'exempt')),
|
|
181
|
+
exemption_reason text CHECK (exemption_reason IS NULL OR
|
|
182
|
+
exemption_reason IN ('founding_tenant', 'internal', 'partner')),
|
|
183
|
+
founding_tenant boolean NOT NULL DEFAULT false,
|
|
184
|
+
granted_by uuid REFERENCES "user"(id),
|
|
185
|
+
granted_at timestamptz,
|
|
186
|
+
-- Isenção com prazo é possível; a do fundador não tem, e `NULL` diz isso.
|
|
187
|
+
expires_on date,
|
|
188
|
+
notes text,
|
|
189
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
190
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
191
|
+
|
|
192
|
+
-- Isentar custa motivo e data. `standard` é o estado gratuito — e o correto
|
|
193
|
+
-- para todo tenant sobre o qual ninguém decidiu nada.
|
|
194
|
+
CONSTRAINT tenant_platform_billing_exemption_needs_reason
|
|
195
|
+
CHECK (billing_mode = 'standard' OR (exemption_reason IS NOT NULL AND granted_at IS NOT NULL))
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
COMMENT ON TABLE tenant_platform_billing IS
|
|
199
|
+
'Cobrança da PLATAFORMA (Baruk → escritório). Não governa a cobrança do escritório aos clientes dele, que é outro domínio e continua ativa.';
|
|
200
|
+
COMMENT ON CONSTRAINT tenant_platform_billing_exemption_needs_reason ON tenant_platform_billing IS
|
|
201
|
+
'Isentar exige motivo e data. Ausência de linha significa cobrança padrão, nunca isenção por omissão.';
|
|
202
|
+
|
|
203
|
+
ALTER TABLE tenant_platform_billing ENABLE ROW LEVEL SECURITY;
|
|
204
|
+
ALTER TABLE tenant_platform_billing FORCE ROW LEVEL SECURITY;
|
|
205
|
+
|
|
206
|
+
-- Leitura: o próprio tenant, ou o operador.
|
|
207
|
+
CREATE POLICY tenant_platform_billing_read ON tenant_platform_billing
|
|
208
|
+
FOR SELECT
|
|
209
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid
|
|
210
|
+
OR current_setting('app.platform_operator', true) = 'true');
|
|
211
|
+
|
|
212
|
+
-- Escrita: SÓ o operador. Uma política por comando — `WITH CHECK` não governa
|
|
213
|
+
-- DELETE, e uma política única deixaria o apagamento da própria isenção (ou da
|
|
214
|
+
-- de outro) fora de qualquer regra.
|
|
215
|
+
CREATE POLICY tenant_platform_billing_insert ON tenant_platform_billing
|
|
216
|
+
FOR INSERT WITH CHECK (current_setting('app.platform_operator', true) = 'true');
|
|
217
|
+
CREATE POLICY tenant_platform_billing_update ON tenant_platform_billing
|
|
218
|
+
FOR UPDATE
|
|
219
|
+
USING (current_setting('app.platform_operator', true) = 'true')
|
|
220
|
+
WITH CHECK (current_setting('app.platform_operator', true) = 'true');
|
|
221
|
+
CREATE POLICY tenant_platform_billing_delete ON tenant_platform_billing
|
|
222
|
+
FOR DELETE USING (current_setting('app.platform_operator', true) = 'true');
|
|
223
|
+
|
|
224
|
+
-- ═══ 4 · O registry municipal deixa de responder só "não sabemos" ════════
|
|
225
|
+
--
|
|
226
|
+
-- `fiscal_coverage` (0058) já traz status, método, credencial exigida, fallback,
|
|
227
|
+
-- fonte e data. Faltavam duas respostas que a política API-first exige ANTES de
|
|
228
|
+
-- alguém cogitar automação de navegador:
|
|
229
|
+
--
|
|
230
|
+
-- `official_api_available` existe caminho estruturado oficial?
|
|
231
|
+
-- `supported_operations` o que ele faz — listar, baixar, consultar evento?
|
|
232
|
+
--
|
|
233
|
+
-- Sem a primeira, "não achei API" e "não procurei" são o mesmo registro, e o
|
|
234
|
+
-- segundo é o que costuma virar um Playwright logando num portal de prefeitura.
|
|
235
|
+
ALTER TABLE fiscal_coverage ADD COLUMN IF NOT EXISTS official_api_available text NOT NULL DEFAULT 'unknown';
|
|
236
|
+
ALTER TABLE fiscal_coverage ADD COLUMN IF NOT EXISTS supported_operations text[] NOT NULL DEFAULT '{}';
|
|
237
|
+
|
|
238
|
+
DO $$
|
|
239
|
+
BEGIN
|
|
240
|
+
IF NOT EXISTS (SELECT FROM pg_constraint WHERE conname = 'fiscal_coverage_official_api_values') THEN
|
|
241
|
+
ALTER TABLE fiscal_coverage ADD CONSTRAINT fiscal_coverage_official_api_values
|
|
242
|
+
CHECK (official_api_available IN ('yes', 'no', 'unknown'));
|
|
243
|
+
END IF;
|
|
244
|
+
END $$;
|
|
245
|
+
|
|
246
|
+
COMMENT ON COLUMN fiscal_coverage.official_api_available IS
|
|
247
|
+
'"no" é uma medição; "unknown" é a ausência dela. Só a primeira autoriza sequer discutir fallback por navegador.';
|
|
248
|
+
|
|
249
|
+
-- ═══ Backfill: as linhas que já afirmavam cobertura ══════════════════════
|
|
250
|
+
--
|
|
251
|
+
-- A 0058 criou quatro linhas `SUPPORTED_OFFICIAL` — NF-e, CT-e e NFS-e nacional
|
|
252
|
+
-- —, todas com a norma citada em `source_reference`. Com a coluna nova nascendo
|
|
253
|
+
-- `unknown`, elas passariam a AFIRMAR cobertura sem ter respondido "existe
|
|
254
|
+
-- caminho oficial?", que é justamente a pergunta que a coluna existe para fazer.
|
|
255
|
+
--
|
|
256
|
+
-- Uma coluna nova sem backfill deixa de fora exatamente as linhas antigas — as
|
|
257
|
+
-- que já estavam em uso. O mesmo raciocínio do `exposure` acima.
|
|
258
|
+
UPDATE fiscal_coverage SET
|
|
259
|
+
official_api_available = 'yes',
|
|
260
|
+
supported_operations = CASE
|
|
261
|
+
WHEN automation_method = 'dfe_nsu_soap' THEN ARRAY['dist_nsu', 'cons_nsu', 'cons_chave']
|
|
262
|
+
WHEN automation_method = 'dfe_nsu_rest' THEN ARRAY['list_by_nsu', 'fetch_document', 'fetch_events']
|
|
263
|
+
ELSE supported_operations
|
|
264
|
+
END
|
|
265
|
+
WHERE coverage_status LIKE 'SUPPORTED%'
|
|
266
|
+
AND official_api_available = 'unknown'
|
|
267
|
+
AND automation_method IN ('dfe_nsu_soap', 'dfe_nsu_rest');
|
|
268
|
+
|
|
269
|
+
-- As linhas dos três municípios do piloto. `SUPPORTED_OFFICIAL` aqui significa
|
|
270
|
+
-- o que já significava na linha nacional do ADN: existe caminho oficial
|
|
271
|
+
-- documentado — e não "já funcionou". Quem responde "já funcionou" é
|
|
272
|
+
-- `digital_certificate.verified_at` somado a um `fiscal_sync_run` completo, e
|
|
273
|
+
-- ambos continuam vazios.
|
|
274
|
+
INSERT INTO fiscal_coverage (
|
|
275
|
+
id, document_type, jurisdiction_scope, jurisdiction_code, provider, coverage_status,
|
|
276
|
+
automation_method, credential_requirement, environments, fallback_type,
|
|
277
|
+
official_api_available, supported_operations,
|
|
278
|
+
last_verified_at, source_reference, notes
|
|
279
|
+
) VALUES
|
|
280
|
+
(gen_random_uuid(), 'nfse', 'municipal', '5208707', 'nfse_adn', 'SUPPORTED_OFFICIAL',
|
|
281
|
+
'dfe_nsu_rest', 'icp_brasil_mtls', ARRAY['homologation', 'production'], 'manual_upload',
|
|
282
|
+
'yes', ARRAY['list_by_nsu', 'fetch_document', 'fetch_events'],
|
|
283
|
+
DATE '2026-09-08',
|
|
284
|
+
'Prefeitura de Goiânia — comunicado oficial de ajuste da NFS-e à Reforma Tributária (vigência 01/01/2026); LC 214/2025 art. 62; Manual dos Contribuintes — APIs do ADN v1.0',
|
|
285
|
+
'Goiânia MANTÉM emissor próprio (Sistema ISS Goiânia, provedor ISSNet) e o compartilhamento com o ADN é feito pela própria administração tributária. Logo o caminho de COLETA é o ADN nacional, por certificado — não o portal municipal. Nenhuma chamada autenticada foi feita a partir deste produto.'),
|
|
286
|
+
|
|
287
|
+
(gen_random_uuid(), 'nfse', 'municipal', '5201405', 'nfse_adn', 'SUPPORTED_OFFICIAL',
|
|
288
|
+
'dfe_nsu_rest', 'icp_brasil_mtls', ARRAY['homologation', 'production'], 'manual_upload',
|
|
289
|
+
'yes', ARRAY['list_by_nsu', 'fetch_document', 'fetch_events'],
|
|
290
|
+
DATE '2026-09-08',
|
|
291
|
+
'Portal oficial da Prefeitura de Aparecida de Goiânia (sistema NFS-e em issnetonline.com.br/aparecida); LC 214/2025 art. 62; Manual dos Contribuintes — APIs do ADN v1.0',
|
|
292
|
+
'Emissor municipal é ISSNet (mesmo provedor de Goiânia e Anápolis). Nenhuma API pública do ISSNet foi verificada; a via oficial de coleta é o ADN. Adesão específica do município ao compartilhamento NÃO foi confirmada em fonte municipal — apenas pela obrigação legal geral.'),
|
|
293
|
+
|
|
294
|
+
(gen_random_uuid(), 'nfse', 'municipal', '5201108', 'nfse_adn', 'SUPPORTED_OFFICIAL',
|
|
295
|
+
'dfe_nsu_rest', 'icp_brasil_mtls', ARRAY['homologation', 'production'], 'manual_upload',
|
|
296
|
+
'yes', ARRAY['list_by_nsu', 'fetch_document', 'fetch_events'],
|
|
297
|
+
DATE '2026-09-08',
|
|
298
|
+
'Prefeitura de Anápolis — Decreto nº 52.525 (03/03/2026, efeitos retroativos a 01/01/2026); LC 214/2025 art. 62; Manual dos Contribuintes — APIs do ADN v1.0',
|
|
299
|
+
'Anápolis mantém emissor municipal próprio (ISS.NET) com webservice local; o comunicado NÃO menciona o ADN. Simples Nacional migra ao emissor nacional a partir de 01/11/2026. A coleta pelo ADN depende do compartilhamento obrigatório, que este produto não verificou.'),
|
|
300
|
+
|
|
301
|
+
-- Estadual GO. A pergunta humana era "notas de entrada e saída"; a resposta
|
|
302
|
+
-- oficial separa as duas, e é essa separação que decide se um conector novo é
|
|
303
|
+
-- necessário — ou se o que falta não tem conector nenhum.
|
|
304
|
+
(gen_random_uuid(), 'nfe', 'state', 'GO', 'sefaz_dfe', 'SUPPORTED_OFFICIAL',
|
|
305
|
+
'dfe_nsu_soap', 'icp_brasil_mtls', ARRAY['homologation', 'production'], 'issuer_export',
|
|
306
|
+
'yes', ARRAY['dist_nsu', 'cons_nsu', 'cons_chave'],
|
|
307
|
+
DATE '2026-09-08',
|
|
308
|
+
'Secretaria da Economia de Goiás — Documentos Fiscais (nfeweb.sefaz.go.gov.br, arquivo XML por certificado digital); NT 2014.002 v1.02c',
|
|
309
|
+
'ENTRADAS: cobertas pela distribuição nacional NFeDistribuicaoDFe, autenticada por certificado ICP-Brasil — nenhuma credencial humana. SAÍDAS: o DF-e não distribui o que a própria empresa emitiu; a origem é o emissor do cliente. O login CPF/senha do portal da SEFAZ-GO NÃO é caminho de coleta estruturada e por isso não é modelado como credencial deste produto.')
|
|
310
|
+
ON CONFLICT DO NOTHING;
|
|
311
|
+
|
|
312
|
+
-- ═══ 5 · A capacidade ════════════════════════════════════════════════════
|
|
313
|
+
--
|
|
314
|
+
-- Chave NOVA, e não bump de `contract_version` — a versão do contrato é global
|
|
315
|
+
-- (0055) e subi-la para exigir schema novo obrigaria todo worker a reconhecer a
|
|
316
|
+
-- versão maior, inclusive os que nada têm a ver com cofre fiscal.
|
|
317
|
+
INSERT INTO platform_capability (key, label, contract_version, declared_by_migration) VALUES
|
|
318
|
+
('office.fiscal-credential-vault.v1',
|
|
319
|
+
'Cofre fiscal: certificado write-only, identidade conferida e autorização de execução única',
|
|
320
|
+
1, '0060')
|
|
321
|
+
ON CONFLICT (key) DO NOTHING;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
-- 0061 — de onde veio cada dado cadastral, e quem mandou nele.
|
|
2
|
+
--
|
|
3
|
+
-- ═══ O defeito que a proveniência existe para tornar indizível ═════════════
|
|
4
|
+
--
|
|
5
|
+
-- Sem ela, um cadastro pré-preenchido por fonte oficial e um cadastro digitado
|
|
6
|
+
-- à mão são a MESMA linha. E aí duas coisas ficam impossíveis:
|
|
7
|
+
--
|
|
8
|
+
-- 1. atualizar sem destruir. Uma segunda consulta traria o valor oficial, e
|
|
9
|
+
-- sobrescrever apagaria a correção que uma pessoa fez de propósito — o
|
|
10
|
+
-- telefone que o escritório sabe estar certo, o e-mail que mudou e a
|
|
11
|
+
-- Receita ainda não sabe.
|
|
12
|
+
-- 2. explicar. "Por que o município deste cliente é Goiânia?" tem respostas
|
|
13
|
+
-- diferentes conforme alguém tenha digitado ou a Receita tenha dito, e a
|
|
14
|
+
-- diferença decide quanto se confia no dado.
|
|
15
|
+
--
|
|
16
|
+
-- A tabela guarda o retrato OFICIAL, ao lado do cadastro — nunca por cima dele.
|
|
17
|
+
-- O cadastro continua sendo o que o escritório afirma; esta linha é o que a
|
|
18
|
+
-- fonte disse, quando disse, e por qual provedor.
|
|
19
|
+
--
|
|
20
|
+
-- ═══ Por que uma tabela, e não colunas em `client` ════════════════════════
|
|
21
|
+
--
|
|
22
|
+
-- Colunas `*_source` em `client` dobrariam a largura da tabela e ainda assim não
|
|
23
|
+
-- guardariam o valor oficial DIVERGENTE — só a etiqueta. É justamente o valor
|
|
24
|
+
-- divergente que a tela de conferência precisa mostrar lado a lado.
|
|
25
|
+
|
|
26
|
+
CREATE TABLE IF NOT EXISTS client_registry_snapshot (
|
|
27
|
+
id uuid PRIMARY KEY,
|
|
28
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
29
|
+
client_id uuid NOT NULL,
|
|
30
|
+
|
|
31
|
+
-- Quem respondeu, e se é fonte oficial. `official = false` NÃO é proibido —
|
|
32
|
+
-- é o que permite registrar um provedor de teste sem que ele se disfarce de
|
|
33
|
+
-- Receita Federal na trilha.
|
|
34
|
+
provider text NOT NULL,
|
|
35
|
+
provider_official boolean NOT NULL DEFAULT false,
|
|
36
|
+
fetched_at timestamptz NOT NULL DEFAULT now(),
|
|
37
|
+
|
|
38
|
+
-- O documento consultado, em dígitos. Guardado aqui porque o `client` pode ser
|
|
39
|
+
-- corrigido depois, e o retrato tem de dizer sobre QUAL número ele fala.
|
|
40
|
+
document_digits text NOT NULL CHECK (document_digits ~ '^[0-9]{14}$'),
|
|
41
|
+
|
|
42
|
+
-- O retrato normalizado. Todo campo é opcional: toda fonte tem lacuna, e uma
|
|
43
|
+
-- lacuna precisa ser dizível como ausência — não como string vazia.
|
|
44
|
+
legal_name text,
|
|
45
|
+
trade_name text,
|
|
46
|
+
registration_status text,
|
|
47
|
+
opened_on date,
|
|
48
|
+
legal_nature text,
|
|
49
|
+
company_size text,
|
|
50
|
+
primary_activity_code text,
|
|
51
|
+
primary_activity_text text,
|
|
52
|
+
secondary_activities jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
53
|
+
street text,
|
|
54
|
+
street_number text,
|
|
55
|
+
complement text,
|
|
56
|
+
district text,
|
|
57
|
+
postal_code text,
|
|
58
|
+
municipality text,
|
|
59
|
+
state_uf text,
|
|
60
|
+
phone text,
|
|
61
|
+
email text,
|
|
62
|
+
share_capital_cents bigint,
|
|
63
|
+
|
|
64
|
+
-- ═══ O silêncio da fonte NÃO é "não" ════════════════════════════════════
|
|
65
|
+
-- `NULL` aqui significa "a fonte não informou", e é diferente de `false`.
|
|
66
|
+
-- Colapsar os dois é como um optante do Simples vira Lucro Presumido por
|
|
67
|
+
-- omissão — e o regime decide quais obrigações o motor aplica.
|
|
68
|
+
simples_optant boolean,
|
|
69
|
+
mei_optant boolean,
|
|
70
|
+
|
|
71
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
72
|
+
|
|
73
|
+
CONSTRAINT client_registry_snapshot_tenant_id_uq UNIQUE (tenant_id, id),
|
|
74
|
+
FOREIGN KEY (tenant_id, client_id) REFERENCES client (tenant_id, id)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
COMMENT ON COLUMN client_registry_snapshot.simples_optant IS
|
|
78
|
+
'NULL = a fonte não informou. NÃO é false. O regime tributário depende disso, e silêncio não é negativa.';
|
|
79
|
+
|
|
80
|
+
-- Um retrato por (cliente, provedor, momento). O índice serve à pergunta real:
|
|
81
|
+
-- "qual foi o último retrato deste cliente?".
|
|
82
|
+
CREATE INDEX IF NOT EXISTS client_registry_snapshot_latest_idx
|
|
83
|
+
ON client_registry_snapshot (tenant_id, client_id, fetched_at DESC);
|
|
84
|
+
|
|
85
|
+
ALTER TABLE client_registry_snapshot ENABLE ROW LEVEL SECURITY;
|
|
86
|
+
ALTER TABLE client_registry_snapshot FORCE ROW LEVEL SECURITY;
|
|
87
|
+
CREATE POLICY client_registry_snapshot_tenant_isolation ON client_registry_snapshot
|
|
88
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
89
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
90
|
+
|
|
91
|
+
-- ═══ A etiqueta por ATRIBUTO ══════════════════════════════════════════════
|
|
92
|
+
--
|
|
93
|
+
-- O retrato acima diz o que a fonte falou. Esta tabela diz o que aconteceu com
|
|
94
|
+
-- cada campo DO CADASTRO: veio da fonte, ou uma pessoa o escreveu?
|
|
95
|
+
--
|
|
96
|
+
-- É ela que faz `HUMAN_OVERRIDE_PRESERVED` ser verificável: um campo marcado
|
|
97
|
+
-- `human` nunca é sobrescrito por atualização automática, e isso é uma consulta
|
|
98
|
+
-- — não uma convenção que alguém precisa lembrar.
|
|
99
|
+
CREATE TABLE IF NOT EXISTS client_field_provenance (
|
|
100
|
+
id uuid PRIMARY KEY,
|
|
101
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
102
|
+
client_id uuid NOT NULL,
|
|
103
|
+
field text NOT NULL,
|
|
104
|
+
origin text NOT NULL CHECK (origin IN ('official_lookup', 'human', 'import')),
|
|
105
|
+
provider text,
|
|
106
|
+
verified_at timestamptz,
|
|
107
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
108
|
+
updated_by uuid REFERENCES "user"(id),
|
|
109
|
+
|
|
110
|
+
CONSTRAINT client_field_provenance_tenant_id_uq UNIQUE (tenant_id, id),
|
|
111
|
+
FOREIGN KEY (tenant_id, client_id) REFERENCES client (tenant_id, id),
|
|
112
|
+
-- Origem oficial sem provedor é afirmação sem autor.
|
|
113
|
+
CONSTRAINT client_field_provenance_official_needs_provider
|
|
114
|
+
CHECK (origin <> 'official_lookup' OR (provider IS NOT NULL AND verified_at IS NOT NULL))
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
CREATE UNIQUE INDEX IF NOT EXISTS client_field_provenance_uq
|
|
118
|
+
ON client_field_provenance (tenant_id, client_id, field);
|
|
119
|
+
|
|
120
|
+
ALTER TABLE client_field_provenance ENABLE ROW LEVEL SECURITY;
|
|
121
|
+
ALTER TABLE client_field_provenance FORCE ROW LEVEL SECURITY;
|
|
122
|
+
CREATE POLICY client_field_provenance_tenant_isolation ON client_field_provenance
|
|
123
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
124
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
125
|
+
|
|
126
|
+
-- ═══ O nome fantasia ══════════════════════════════════════════════════════
|
|
127
|
+
--
|
|
128
|
+
-- `client` guarda `display_name` e `legal_name`, e não tinha onde pôr o nome
|
|
129
|
+
-- fantasia — que é o que a fonte oficial devolve e o que a equipe usa para
|
|
130
|
+
-- falar do cliente ("HIPER FESTA", não "OLIVEIRA PRODUTOS PARA FESTAS LTDA").
|
|
131
|
+
ALTER TABLE client ADD COLUMN IF NOT EXISTS trade_name text;
|
|
132
|
+
|
|
133
|
+
COMMENT ON COLUMN client.trade_name IS
|
|
134
|
+
'Nome fantasia. Distinto de display_name (como o escritório chama) e de legal_name (razão social).';
|
|
135
|
+
|
|
136
|
+
INSERT INTO platform_capability (key, label, contract_version, declared_by_migration) VALUES
|
|
137
|
+
('office.client-registry-provenance.v1',
|
|
138
|
+
'Retrato de fonte oficial e proveniência por atributo do cadastro do cliente',
|
|
139
|
+
1, '0061')
|
|
140
|
+
ON CONFLICT (key) DO NOTHING;
|
|
141
|
+
|
|
142
|
+
-- ═══ A consulta em si — cota, cache e trilha na MESMA linha ═══════════════
|
|
143
|
+
--
|
|
144
|
+
-- Esta tabela existe por três perguntas que não têm outra fonte:
|
|
145
|
+
--
|
|
146
|
+
-- 1. **quantas consultas este escritório já fez na janela?** Sem contagem
|
|
147
|
+
-- persistente, um contador em memória zera a cada redeploy e some quando
|
|
148
|
+
-- há duas instâncias — que é exatamente quando o limite importa.
|
|
149
|
+
-- 2. **já perguntamos este CNPJ há pouco?** Uma segunda consulta idêntica em
|
|
150
|
+
-- cinco minutos gasta cota de um contrato pago para reobter o que já se
|
|
151
|
+
-- sabe. O `payload` é o cache; o TTL vive no código.
|
|
152
|
+
-- 3. **quem perguntou por qual empresa?** Consulta de CNPJ é rastreável por
|
|
153
|
+
-- dever próprio: é a pergunta "esse escritório andou varrendo documentos?".
|
|
154
|
+
--
|
|
155
|
+
-- **Sem FK para `client`, e é de propósito.** A consulta acontece ANTES de o
|
|
156
|
+
-- cliente existir — o operador digita o CNPJ numa tela de cadastro vazia. Uma FK
|
|
157
|
+
-- aqui tornaria impossível registrar justamente a consulta mais comum.
|
|
158
|
+
CREATE TABLE IF NOT EXISTS client_registry_lookup (
|
|
159
|
+
id uuid PRIMARY KEY,
|
|
160
|
+
tenant_id uuid NOT NULL REFERENCES tenant(id),
|
|
161
|
+
document_digits text NOT NULL CHECK (document_digits ~ '^[0-9]{14}$'),
|
|
162
|
+
provider text NOT NULL,
|
|
163
|
+
outcome text NOT NULL CHECK (outcome IN ('ok', 'failed')),
|
|
164
|
+
-- O motivo da recusa, quando houve. Vocabulário fechado no código
|
|
165
|
+
-- (`CompanyLookupFailure`); aqui fica aberto para não travar a migration num
|
|
166
|
+
-- vocabulário que ainda vai crescer com o primeiro provedor real.
|
|
167
|
+
failure_reason text,
|
|
168
|
+
-- O retrato devolvido, quando houve. É o cache: uma repetição dentro do TTL
|
|
169
|
+
-- é respondida daqui sem tocar a rede. NULL em toda linha `failed` — falha
|
|
170
|
+
-- não se cacheia, senão uma indisponibilidade de um minuto ficaria colada
|
|
171
|
+
-- no CNPJ pelo resto do TTL.
|
|
172
|
+
payload jsonb,
|
|
173
|
+
requested_by uuid REFERENCES "user"(id),
|
|
174
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
175
|
+
|
|
176
|
+
CONSTRAINT client_registry_lookup_tenant_id_uq UNIQUE (tenant_id, id),
|
|
177
|
+
CONSTRAINT client_registry_lookup_failure_has_no_payload
|
|
178
|
+
CHECK (outcome = 'ok' OR payload IS NULL)
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
-- A cota pergunta "quantas linhas deste tenant desde X"; o cache pergunta
|
|
182
|
+
-- "qual a última linha `ok` deste documento". Um índice serve às duas.
|
|
183
|
+
CREATE INDEX IF NOT EXISTS client_registry_lookup_quota_idx
|
|
184
|
+
ON client_registry_lookup (tenant_id, created_at DESC);
|
|
185
|
+
CREATE INDEX IF NOT EXISTS client_registry_lookup_cache_idx
|
|
186
|
+
ON client_registry_lookup (tenant_id, document_digits, created_at DESC)
|
|
187
|
+
WHERE outcome = 'ok';
|
|
188
|
+
|
|
189
|
+
ALTER TABLE client_registry_lookup ENABLE ROW LEVEL SECURITY;
|
|
190
|
+
ALTER TABLE client_registry_lookup FORCE ROW LEVEL SECURITY;
|
|
191
|
+
CREATE POLICY client_registry_lookup_tenant_isolation ON client_registry_lookup
|
|
192
|
+
USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
|
|
193
|
+
WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
-- 0062 — o primeiro contato, e a diferença entre "existe" e "nós fizemos".
|
|
2
|
+
--
|
|
3
|
+
-- ═══ Dois defeitos, e por que eles são o mesmo defeito ════════════════════
|
|
4
|
+
--
|
|
5
|
+
-- **1. O impasse.** A execução exigia `verified_at`; `verified_at` significa "o
|
|
6
|
+
-- ambiente oficial já aceitou"; e só uma execução produz esse aceite. A primeira
|
|
7
|
+
-- consulta real era inalcançável por construção — não por configuração, não por
|
|
8
|
+
-- falta de certificado. A auditoria da C2 encontrou o ciclo fechado.
|
|
9
|
+
--
|
|
10
|
+
-- **2. A cobertura mentindo por omissão.** `coverage_status = 'SUPPORTED_OFFICIAL'`
|
|
11
|
+
-- responde "a norma oferece um caminho oficial?". A tela mostrava isso ao lado do
|
|
12
|
+
-- botão de autorizar, e o operador lia "o Baruk já fala com esse serviço". Para
|
|
13
|
+
-- `sefaz_dfe` isso era falso: não existe adaptador, só a string do conector.
|
|
14
|
+
--
|
|
15
|
+
-- Os dois são a mesma confusão — **tratar o que o mundo oferece como o que este
|
|
16
|
+
-- produto construiu**. A correção é a mesma nos dois: separar os fatos em
|
|
17
|
+
-- colunas próprias e obrigar cada portão a citar a sua.
|
|
18
|
+
|
|
19
|
+
-- ═══ 1 · A verdade da capacidade, por camada ══════════════════════════════
|
|
20
|
+
--
|
|
21
|
+
-- `official_api_available` já respondia "existe API oficial?". Faltavam as duas
|
|
22
|
+
-- perguntas seguintes, e é a ausência delas que produzia a leitura errada.
|
|
23
|
+
ALTER TABLE fiscal_coverage
|
|
24
|
+
ADD COLUMN IF NOT EXISTS connector_implemented boolean NOT NULL DEFAULT false;
|
|
25
|
+
ALTER TABLE fiscal_coverage
|
|
26
|
+
ADD COLUMN IF NOT EXISTS protocol_verified boolean NOT NULL DEFAULT false;
|
|
27
|
+
|
|
28
|
+
COMMENT ON COLUMN fiscal_coverage.official_api_available IS
|
|
29
|
+
'A NORMA oferece um caminho oficial? Fato do mundo, independente deste produto.';
|
|
30
|
+
COMMENT ON COLUMN fiscal_coverage.connector_implemented IS
|
|
31
|
+
'ESTE produto tem adaptador para o caminho? Fato do repositório. `sefaz_dfe` era SUPPORTED_OFFICIAL sem uma linha de adaptador — foi o que esta coluna passou a tornar dizível.';
|
|
32
|
+
COMMENT ON COLUMN fiscal_coverage.protocol_verified IS
|
|
33
|
+
'O envelope/contrato do serviço foi conferido contra o serviço REAL? Ler documentação não conta; para o ADN, os nomes dos campos do envelope não estão publicados em lugar acessível.';
|
|
34
|
+
|
|
35
|
+
-- Backfill explícito, e não default silencioso.
|
|
36
|
+
--
|
|
37
|
+
-- `DEFAULT false` deixaria toda linha existente afirmando "não implementado", o
|
|
38
|
+
-- que por acaso está certo para `sefaz_dfe` e errado para `nfse_adn`. Um acerto
|
|
39
|
+
-- por acaso é o que some no primeiro conector novo.
|
|
40
|
+
UPDATE fiscal_coverage SET connector_implemented = true
|
|
41
|
+
WHERE provider = 'nfse_adn';
|
|
42
|
+
UPDATE fiscal_coverage SET connector_implemented = false
|
|
43
|
+
WHERE provider = 'sefaz_dfe';
|
|
44
|
+
-- Nenhum conector tem o protocolo conferido contra o serviço real hoje. O do
|
|
45
|
+
-- ADN depende de um Swagger servido pelo próprio host que exige mTLS.
|
|
46
|
+
UPDATE fiscal_coverage SET protocol_verified = false;
|
|
47
|
+
|
|
48
|
+
-- ═══ 2 · A autorização passa a apontar para UM certificado ════════════════
|
|
49
|
+
--
|
|
50
|
+
-- Sem isto, trocar o certificado depois de autorizar mantinha a autorização de
|
|
51
|
+
-- pé — e a execução aconteceria com material que ninguém aprovou. O caso não é
|
|
52
|
+
-- teórico: substituir certificado é a operação normal quando um vence.
|
|
53
|
+
ALTER TABLE fiscal_run_authorization
|
|
54
|
+
ADD COLUMN IF NOT EXISTS credential_fingerprint text;
|
|
55
|
+
|
|
56
|
+
COMMENT ON COLUMN fiscal_run_authorization.credential_fingerprint IS
|
|
57
|
+
'sha256 do DER do certificado vigente quando a autorização foi emitida. O executor recusa quando o certificado atual difere: autorizar é aprovar UM material, não uma intenção.';
|
|
58
|
+
|
|
59
|
+
-- ═══ 3 · O primeiro contato é um ATO, e ele tem registro próprio ══════════
|
|
60
|
+
--
|
|
61
|
+
-- Por que uma coluna e não um tipo de autorização separado: a autorização já é
|
|
62
|
+
-- one-shot, read-only, escopada e expirável. O primeiro contato não precisa de
|
|
63
|
+
-- outra tabela — precisa de uma DECLARAÇÃO de que quem autorizou sabia que a
|
|
64
|
+
-- credencial ainda não fora aceita por ninguém.
|
|
65
|
+
--
|
|
66
|
+
-- `false` como padrão importa: uma autorização comum continua exigindo
|
|
67
|
+
-- credencial verificada. Só quem marca este campo aceita o risco do bootstrap.
|
|
68
|
+
ALTER TABLE fiscal_run_authorization
|
|
69
|
+
ADD COLUMN IF NOT EXISTS first_contact boolean NOT NULL DEFAULT false;
|
|
70
|
+
|
|
71
|
+
COMMENT ON COLUMN fiscal_run_authorization.first_contact IS
|
|
72
|
+
'Autorização de PRIMEIRO CONTATO: aceita credencial válida localmente e ainda não aceita por nenhum ambiente oficial. É o único caminho que resolve o impasse do verified_at, e nenhum agendador pode emiti-la.';
|
|
73
|
+
|
|
74
|
+
-- Quem executou, e por qual porta.
|
|
75
|
+
--
|
|
76
|
+
-- `manual` é o único valor que o primeiro contato admite, e o CHECK abaixo é
|
|
77
|
+
-- quem garante isso — não um `if` em TypeScript que alguém remove.
|
|
78
|
+
ALTER TABLE fiscal_run_authorization
|
|
79
|
+
ADD COLUMN IF NOT EXISTS trigger_kind text NOT NULL DEFAULT 'manual';
|
|
80
|
+
|
|
81
|
+
ALTER TABLE fiscal_run_authorization
|
|
82
|
+
DROP CONSTRAINT IF EXISTS fiscal_run_authorization_trigger_kind_check;
|
|
83
|
+
ALTER TABLE fiscal_run_authorization
|
|
84
|
+
ADD CONSTRAINT fiscal_run_authorization_trigger_kind_check
|
|
85
|
+
CHECK (trigger_kind IN ('manual', 'scheduled'));
|
|
86
|
+
|
|
87
|
+
-- ═══ O CHECK que impede o agendador de fazer o bootstrap ══════════════════
|
|
88
|
+
--
|
|
89
|
+
-- Está no banco, e não no orquestrador, porque a regra tem de sobreviver a um
|
|
90
|
+
-- refactor do orquestrador. Um cron que tentasse emitir autorização de primeiro
|
|
91
|
+
-- contato viola a linha abaixo e a transação morre.
|
|
92
|
+
ALTER TABLE fiscal_run_authorization
|
|
93
|
+
DROP CONSTRAINT IF EXISTS fiscal_run_authorization_first_contact_is_manual;
|
|
94
|
+
ALTER TABLE fiscal_run_authorization
|
|
95
|
+
ADD CONSTRAINT fiscal_run_authorization_first_contact_is_manual
|
|
96
|
+
CHECK (first_contact = false OR trigger_kind = 'manual');
|
|
97
|
+
|
|
98
|
+
COMMENT ON CONSTRAINT fiscal_run_authorization_first_contact_is_manual ON fiscal_run_authorization IS
|
|
99
|
+
'Primeiro contato é ato de gente. Um agendador que o tentasse estaria decidindo, sozinho, gastar o certificado de um terceiro contra a Receita pela primeira vez.';
|
|
100
|
+
|
|
101
|
+
-- ═══ 4 · A habilitação fiscal do tenant, com granularidade ════════════════
|
|
102
|
+
--
|
|
103
|
+
-- `tenant_fiscal_automation` já existe (0058) e responde por MODO — qual
|
|
104
|
+
-- ambiente o escritório declarou operar. Ela continua sendo a chave-geral.
|
|
105
|
+
--
|
|
106
|
+
-- O que faltava era o outro lado do par: a matrícula POR CLIENTE já existia em
|
|
107
|
+
-- `client_fiscal_enrollment` (0058), também por `document_type`. Nada disso
|
|
108
|
+
-- precisa de tabela nova — precisa de superfície e de auditoria, que vêm no
|
|
109
|
+
-- código desta mesma frente.
|
|
110
|
+
--
|
|
111
|
+
-- Registrado aqui para quem ler a migration procurando as tabelas e não as
|
|
112
|
+
-- encontrar: elas existem desde a 0058, e esta frente as LIGA, não as cria.
|
|
113
|
+
|
|
114
|
+
-- ═══ 5 · A capacidade ═════════════════════════════════════════════════════
|
|
115
|
+
INSERT INTO platform_capability (key, label, contract_version, declared_by_migration) VALUES
|
|
116
|
+
('office.fiscal-first-contact.v1',
|
|
117
|
+
'Primeiro contato fiscal: autorização one-shot que aceita credencial válida só localmente',
|
|
118
|
+
1, '0062')
|
|
119
|
+
ON CONFLICT (key) DO NOTHING;
|