@baruk/core 0.4.2 → 0.5.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.
Files changed (465) hide show
  1. package/.baruk-provenance.json +4 -4
  2. package/CHANGELOG.md +42 -0
  3. package/dist/audit/repository.d.ts +33 -1
  4. package/dist/audit/repository.d.ts.map +1 -1
  5. package/dist/audit/repository.js +41 -7
  6. package/dist/audit/repository.js.map +1 -1
  7. package/dist/auth/service.d.ts +21 -0
  8. package/dist/auth/service.d.ts.map +1 -1
  9. package/dist/auth/service.js +46 -1
  10. package/dist/auth/service.js.map +1 -1
  11. package/dist/billing/ar-repository.d.ts +41 -1
  12. package/dist/billing/ar-repository.d.ts.map +1 -1
  13. package/dist/billing/ar-repository.js +82 -6
  14. package/dist/billing/ar-repository.js.map +1 -1
  15. package/dist/billing/provider-account.d.ts +38 -0
  16. package/dist/billing/provider-account.d.ts.map +1 -1
  17. package/dist/billing/provider-account.js +58 -2
  18. package/dist/billing/provider-account.js.map +1 -1
  19. package/dist/billing/repository.d.ts +44 -0
  20. package/dist/billing/repository.d.ts.map +1 -1
  21. package/dist/billing/repository.js +49 -5
  22. package/dist/billing/repository.js.map +1 -1
  23. package/dist/cjs/audit/repository.js +41 -7
  24. package/dist/cjs/audit/repository.js.map +1 -1
  25. package/dist/cjs/auth/service.js +46 -1
  26. package/dist/cjs/auth/service.js.map +1 -1
  27. package/dist/cjs/billing/ar-repository.js +82 -6
  28. package/dist/cjs/billing/ar-repository.js.map +1 -1
  29. package/dist/cjs/billing/provider-account.js +60 -1
  30. package/dist/cjs/billing/provider-account.js.map +1 -1
  31. package/dist/cjs/billing/repository.js +51 -5
  32. package/dist/cjs/billing/repository.js.map +1 -1
  33. package/dist/cjs/clients/ibge.js +103 -0
  34. package/dist/cjs/clients/ibge.js.map +1 -0
  35. package/dist/cjs/clients/repository.js +186 -9
  36. package/dist/cjs/clients/repository.js.map +1 -1
  37. package/dist/cjs/collection/branding.js +190 -0
  38. package/dist/cjs/collection/branding.js.map +1 -1
  39. package/dist/cjs/collection/clearance-store.js +74 -0
  40. package/dist/cjs/collection/clearance-store.js.map +1 -0
  41. package/dist/cjs/collection/communication-runtime.js +65 -2
  42. package/dist/cjs/collection/communication-runtime.js.map +1 -1
  43. package/dist/cjs/collection/engine.js +20 -0
  44. package/dist/cjs/collection/engine.js.map +1 -1
  45. package/dist/cjs/collection/policy.js +29 -1
  46. package/dist/cjs/collection/policy.js.map +1 -1
  47. package/dist/cjs/communication/clearance.js +18 -0
  48. package/dist/cjs/communication/clearance.js.map +1 -0
  49. package/dist/cjs/communication/dry-run-scenario.js +5 -0
  50. package/dist/cjs/communication/dry-run-scenario.js.map +1 -1
  51. package/dist/cjs/communication/engine.js +12 -0
  52. package/dist/cjs/communication/engine.js.map +1 -1
  53. package/dist/cjs/communication/policy.js.map +1 -1
  54. package/dist/cjs/competence/business-days.js +155 -0
  55. package/dist/cjs/competence/business-days.js.map +1 -0
  56. package/dist/cjs/competence/catalog-validation.js +174 -0
  57. package/dist/cjs/competence/catalog-validation.js.map +1 -0
  58. package/dist/cjs/competence/obligation-preview.js +190 -0
  59. package/dist/cjs/competence/obligation-preview.js.map +1 -0
  60. package/dist/cjs/competence/repository.js +330 -17
  61. package/dist/cjs/competence/repository.js.map +1 -1
  62. package/dist/cjs/dashboard/pilot-panel.js +90 -0
  63. package/dist/cjs/dashboard/pilot-panel.js.map +1 -0
  64. package/dist/cjs/dashboard/repository.js +11 -1
  65. package/dist/cjs/dashboard/repository.js.map +1 -1
  66. package/dist/cjs/db/client.js +17 -11
  67. package/dist/cjs/db/client.js.map +1 -1
  68. package/dist/cjs/db/provision-e2e-identity.js +111 -0
  69. package/dist/cjs/db/provision-e2e-identity.js.map +1 -0
  70. package/dist/cjs/fiscal/applicability.js +164 -0
  71. package/dist/cjs/fiscal/applicability.js.map +1 -0
  72. package/dist/cjs/fiscal/conditions.js +198 -0
  73. package/dist/cjs/fiscal/conditions.js.map +1 -0
  74. package/dist/cjs/fiscal/contracts/nfse-adn-contract.js +390 -0
  75. package/dist/cjs/fiscal/contracts/nfse-adn-contract.js.map +1 -0
  76. package/dist/cjs/fiscal/contracts/nfse-adn-endpoint.js +108 -0
  77. package/dist/cjs/fiscal/contracts/nfse-adn-endpoint.js.map +1 -0
  78. package/dist/cjs/fiscal/contracts/nfse-adn-envelope.js +220 -0
  79. package/dist/cjs/fiscal/contracts/nfse-adn-envelope.js.map +1 -0
  80. package/dist/cjs/fiscal/coverage/model.js +127 -0
  81. package/dist/cjs/fiscal/coverage/model.js.map +1 -0
  82. package/dist/cjs/fiscal/coverage/requests.js +99 -0
  83. package/dist/cjs/fiscal/coverage/requests.js.map +1 -0
  84. package/dist/cjs/fiscal/credentials/material.js +168 -0
  85. package/dist/cjs/fiscal/credentials/material.js.map +1 -0
  86. package/dist/cjs/fiscal/credentials/readiness.js +163 -0
  87. package/dist/cjs/fiscal/credentials/readiness.js.map +1 -0
  88. package/dist/cjs/fiscal/eligibility.js +199 -0
  89. package/dist/cjs/fiscal/eligibility.js.map +1 -0
  90. package/dist/cjs/fiscal/ingestion/__fixtures__/nfse.js +128 -0
  91. package/dist/cjs/fiscal/ingestion/__fixtures__/nfse.js.map +1 -0
  92. package/dist/cjs/fiscal/ingestion/adn-transport.js +229 -0
  93. package/dist/cjs/fiscal/ingestion/adn-transport.js.map +1 -0
  94. package/dist/cjs/fiscal/ingestion/direction.js +36 -0
  95. package/dist/cjs/fiscal/ingestion/direction.js.map +1 -0
  96. package/dist/cjs/fiscal/ingestion/nfse-adn.js +228 -0
  97. package/dist/cjs/fiscal/ingestion/nfse-adn.js.map +1 -0
  98. package/dist/cjs/fiscal/ingestion/pipeline.js +704 -0
  99. package/dist/cjs/fiscal/ingestion/pipeline.js.map +1 -0
  100. package/dist/cjs/fiscal/ingestion/provider.js +51 -0
  101. package/dist/cjs/fiscal/ingestion/provider.js.map +1 -0
  102. package/dist/cjs/fiscal/ingestion/repository.js +132 -0
  103. package/dist/cjs/fiscal/ingestion/repository.js.map +1 -0
  104. package/dist/cjs/fiscal/ingestion/synthetic-provider.js +103 -0
  105. package/dist/cjs/fiscal/ingestion/synthetic-provider.js.map +1 -0
  106. package/dist/cjs/fiscal/ingestion/synthetic-transport-types.js +13 -0
  107. package/dist/cjs/fiscal/ingestion/synthetic-transport-types.js.map +1 -0
  108. package/dist/cjs/fiscal/ingestion/synthetic-transport.js +61 -0
  109. package/dist/cjs/fiscal/ingestion/synthetic-transport.js.map +1 -0
  110. package/dist/cjs/fiscal/ingestion/xml-reader.js +121 -0
  111. package/dist/cjs/fiscal/ingestion/xml-reader.js.map +1 -0
  112. package/dist/cjs/fiscal/repository.js +470 -0
  113. package/dist/cjs/fiscal/repository.js.map +1 -0
  114. package/dist/cjs/fiscal/sync/circuit.js +124 -0
  115. package/dist/cjs/fiscal/sync/circuit.js.map +1 -0
  116. package/dist/cjs/fiscal/sync/intervention.js +140 -0
  117. package/dist/cjs/fiscal/sync/intervention.js.map +1 -0
  118. package/dist/cjs/fiscal/sync/lease.js +146 -0
  119. package/dist/cjs/fiscal/sync/lease.js.map +1 -0
  120. package/dist/cjs/fiscal/sync/observability.js +244 -0
  121. package/dist/cjs/fiscal/sync/observability.js.map +1 -0
  122. package/dist/cjs/fiscal/sync/orchestrator.js +490 -0
  123. package/dist/cjs/fiscal/sync/orchestrator.js.map +1 -0
  124. package/dist/cjs/fiscal/sync/policy.js +143 -0
  125. package/dist/cjs/fiscal/sync/policy.js.map +1 -0
  126. package/dist/cjs/fiscal/sync/reprocess.js +241 -0
  127. package/dist/cjs/fiscal/sync/reprocess.js.map +1 -0
  128. package/dist/cjs/fiscal/sync/retry.js +183 -0
  129. package/dist/cjs/fiscal/sync/retry.js.map +1 -0
  130. package/dist/cjs/fiscal/sync/secret-boundary.js +123 -0
  131. package/dist/cjs/fiscal/sync/secret-boundary.js.map +1 -0
  132. package/dist/cjs/fiscal/transport/https.js +309 -0
  133. package/dist/cjs/fiscal/transport/https.js.map +1 -0
  134. package/dist/cjs/fiscal/transport/synthetic-tls.js +328 -0
  135. package/dist/cjs/fiscal/transport/synthetic-tls.js.map +1 -0
  136. package/dist/cjs/fiscal/transport/types.js +93 -0
  137. package/dist/cjs/fiscal/transport/types.js.map +1 -0
  138. package/dist/cjs/import/br-documents.js +85 -0
  139. package/dist/cjs/import/br-documents.js.map +1 -0
  140. package/dist/cjs/import/clients-import.js +347 -40
  141. package/dist/cjs/import/clients-import.js.map +1 -1
  142. package/dist/cjs/index.js +316 -11
  143. package/dist/cjs/index.js.map +1 -1
  144. package/dist/cjs/legal/documents.js +100 -15
  145. package/dist/cjs/legal/documents.js.map +1 -1
  146. package/dist/cjs/legal/index.js +3 -1
  147. package/dist/cjs/legal/index.js.map +1 -1
  148. package/dist/cjs/legal/types.js.map +1 -1
  149. package/dist/cjs/onboarding/persistence.js +4 -4
  150. package/dist/cjs/onboarding/persistence.js.map +1 -1
  151. package/dist/cjs/pilot/go-live-checklist.js +212 -0
  152. package/dist/cjs/pilot/go-live-checklist.js.map +1 -0
  153. package/dist/cjs/pilot/milestone.js +79 -0
  154. package/dist/cjs/pilot/milestone.js.map +1 -0
  155. package/dist/cjs/platform/capabilities.js +144 -0
  156. package/dist/cjs/platform/capabilities.js.map +1 -0
  157. package/dist/cjs/platform/job-contract.js +411 -0
  158. package/dist/cjs/platform/job-contract.js.map +1 -0
  159. package/dist/cjs/rbac/catalog.js +34 -0
  160. package/dist/cjs/rbac/catalog.js.map +1 -1
  161. package/dist/cjs/subscription-billing/index.js +2 -1
  162. package/dist/cjs/subscription-billing/index.js.map +1 -1
  163. package/dist/cjs/subscription-billing/service.js +153 -77
  164. package/dist/cjs/subscription-billing/service.js.map +1 -1
  165. package/dist/cjs/tenancy/features.js +131 -0
  166. package/dist/cjs/tenancy/features.js.map +1 -0
  167. package/dist/cjs/tenancy/settings.js +224 -0
  168. package/dist/cjs/tenancy/settings.js.map +1 -0
  169. package/dist/cjs/users/repository.js +24 -1
  170. package/dist/cjs/users/repository.js.map +1 -1
  171. package/dist/clients/ibge.d.ts +17 -0
  172. package/dist/clients/ibge.d.ts.map +1 -0
  173. package/dist/clients/ibge.js +98 -0
  174. package/dist/clients/ibge.js.map +1 -0
  175. package/dist/clients/repository.d.ts +154 -0
  176. package/dist/clients/repository.d.ts.map +1 -1
  177. package/dist/clients/repository.js +182 -9
  178. package/dist/clients/repository.js.map +1 -1
  179. package/dist/collection/branding.d.ts +65 -0
  180. package/dist/collection/branding.d.ts.map +1 -1
  181. package/dist/collection/branding.js +186 -0
  182. package/dist/collection/branding.js.map +1 -1
  183. package/dist/collection/clearance-store.d.ts +39 -0
  184. package/dist/collection/clearance-store.d.ts.map +1 -0
  185. package/dist/collection/clearance-store.js +69 -0
  186. package/dist/collection/clearance-store.js.map +1 -0
  187. package/dist/collection/communication-runtime.d.ts +37 -0
  188. package/dist/collection/communication-runtime.d.ts.map +1 -1
  189. package/dist/collection/communication-runtime.js +63 -1
  190. package/dist/collection/communication-runtime.js.map +1 -1
  191. package/dist/collection/engine.d.ts +23 -0
  192. package/dist/collection/engine.d.ts.map +1 -1
  193. package/dist/collection/engine.js +20 -0
  194. package/dist/collection/engine.js.map +1 -1
  195. package/dist/collection/policy.d.ts +25 -0
  196. package/dist/collection/policy.d.ts.map +1 -1
  197. package/dist/collection/policy.js +27 -0
  198. package/dist/collection/policy.js.map +1 -1
  199. package/dist/communication/clearance.d.ts +53 -0
  200. package/dist/communication/clearance.d.ts.map +1 -0
  201. package/dist/communication/clearance.js +15 -0
  202. package/dist/communication/clearance.js.map +1 -0
  203. package/dist/communication/dry-run-scenario.d.ts.map +1 -1
  204. package/dist/communication/dry-run-scenario.js +5 -0
  205. package/dist/communication/dry-run-scenario.js.map +1 -1
  206. package/dist/communication/engine.d.ts +10 -0
  207. package/dist/communication/engine.d.ts.map +1 -1
  208. package/dist/communication/engine.js +12 -0
  209. package/dist/communication/engine.js.map +1 -1
  210. package/dist/communication/policy.d.ts +16 -0
  211. package/dist/communication/policy.d.ts.map +1 -1
  212. package/dist/communication/policy.js.map +1 -1
  213. package/dist/competence/business-days.d.ts +51 -0
  214. package/dist/competence/business-days.d.ts.map +1 -0
  215. package/dist/competence/business-days.js +145 -0
  216. package/dist/competence/business-days.js.map +1 -0
  217. package/dist/competence/catalog-validation.d.ts +86 -0
  218. package/dist/competence/catalog-validation.d.ts.map +1 -0
  219. package/dist/competence/catalog-validation.js +168 -0
  220. package/dist/competence/catalog-validation.js.map +1 -0
  221. package/dist/competence/obligation-preview.d.ts +103 -0
  222. package/dist/competence/obligation-preview.d.ts.map +1 -0
  223. package/dist/competence/obligation-preview.js +184 -0
  224. package/dist/competence/obligation-preview.js.map +1 -0
  225. package/dist/competence/repository.d.ts +139 -1
  226. package/dist/competence/repository.d.ts.map +1 -1
  227. package/dist/competence/repository.js +325 -17
  228. package/dist/competence/repository.js.map +1 -1
  229. package/dist/dashboard/pilot-panel.d.ts +100 -0
  230. package/dist/dashboard/pilot-panel.d.ts.map +1 -0
  231. package/dist/dashboard/pilot-panel.js +87 -0
  232. package/dist/dashboard/pilot-panel.js.map +1 -0
  233. package/dist/dashboard/repository.d.ts.map +1 -1
  234. package/dist/dashboard/repository.js +11 -1
  235. package/dist/dashboard/repository.js.map +1 -1
  236. package/dist/db/client.d.ts +45 -0
  237. package/dist/db/client.d.ts.map +1 -1
  238. package/dist/db/client.js +16 -11
  239. package/dist/db/client.js.map +1 -1
  240. package/dist/db/migrate.d.ts +36 -1
  241. package/dist/db/migrate.d.ts.map +1 -1
  242. package/dist/db/migrate.js +199 -32
  243. package/dist/db/migrate.js.map +1 -1
  244. package/dist/db/provision-e2e-identity.d.ts +2 -0
  245. package/dist/db/provision-e2e-identity.d.ts.map +1 -0
  246. package/dist/db/provision-e2e-identity.js +109 -0
  247. package/dist/db/provision-e2e-identity.js.map +1 -0
  248. package/dist/fiscal/applicability.d.ts +73 -0
  249. package/dist/fiscal/applicability.d.ts.map +1 -0
  250. package/dist/fiscal/applicability.js +160 -0
  251. package/dist/fiscal/applicability.js.map +1 -0
  252. package/dist/fiscal/conditions.d.ts +99 -0
  253. package/dist/fiscal/conditions.d.ts.map +1 -0
  254. package/dist/fiscal/conditions.js +190 -0
  255. package/dist/fiscal/conditions.js.map +1 -0
  256. package/dist/fiscal/contracts/nfse-adn-contract.d.ts +315 -0
  257. package/dist/fiscal/contracts/nfse-adn-contract.d.ts.map +1 -0
  258. package/dist/fiscal/contracts/nfse-adn-contract.js +386 -0
  259. package/dist/fiscal/contracts/nfse-adn-contract.js.map +1 -0
  260. package/dist/fiscal/contracts/nfse-adn-endpoint.d.ts +13 -0
  261. package/dist/fiscal/contracts/nfse-adn-endpoint.d.ts.map +1 -0
  262. package/dist/fiscal/contracts/nfse-adn-endpoint.js +103 -0
  263. package/dist/fiscal/contracts/nfse-adn-endpoint.js.map +1 -0
  264. package/dist/fiscal/contracts/nfse-adn-envelope.d.ts +77 -0
  265. package/dist/fiscal/contracts/nfse-adn-envelope.d.ts.map +1 -0
  266. package/dist/fiscal/contracts/nfse-adn-envelope.js +215 -0
  267. package/dist/fiscal/contracts/nfse-adn-envelope.js.map +1 -0
  268. package/dist/fiscal/coverage/model.d.ts +86 -0
  269. package/dist/fiscal/coverage/model.d.ts.map +1 -0
  270. package/dist/fiscal/coverage/model.js +120 -0
  271. package/dist/fiscal/coverage/model.js.map +1 -0
  272. package/dist/fiscal/coverage/requests.d.ts +70 -0
  273. package/dist/fiscal/coverage/requests.d.ts.map +1 -0
  274. package/dist/fiscal/coverage/requests.js +95 -0
  275. package/dist/fiscal/coverage/requests.js.map +1 -0
  276. package/dist/fiscal/credentials/material.d.ts +81 -0
  277. package/dist/fiscal/credentials/material.d.ts.map +1 -0
  278. package/dist/fiscal/credentials/material.js +164 -0
  279. package/dist/fiscal/credentials/material.js.map +1 -0
  280. package/dist/fiscal/credentials/readiness.d.ts +92 -0
  281. package/dist/fiscal/credentials/readiness.d.ts.map +1 -0
  282. package/dist/fiscal/credentials/readiness.js +159 -0
  283. package/dist/fiscal/credentials/readiness.js.map +1 -0
  284. package/dist/fiscal/eligibility.d.ts +106 -0
  285. package/dist/fiscal/eligibility.d.ts.map +1 -0
  286. package/dist/fiscal/eligibility.js +194 -0
  287. package/dist/fiscal/eligibility.js.map +1 -0
  288. package/dist/fiscal/ingestion/__fixtures__/nfse.d.ts +57 -0
  289. package/dist/fiscal/ingestion/__fixtures__/nfse.d.ts.map +1 -0
  290. package/dist/fiscal/ingestion/__fixtures__/nfse.js +121 -0
  291. package/dist/fiscal/ingestion/__fixtures__/nfse.js.map +1 -0
  292. package/dist/fiscal/ingestion/adn-transport.d.ts +123 -0
  293. package/dist/fiscal/ingestion/adn-transport.d.ts.map +1 -0
  294. package/dist/fiscal/ingestion/adn-transport.js +220 -0
  295. package/dist/fiscal/ingestion/adn-transport.js.map +1 -0
  296. package/dist/fiscal/ingestion/direction.d.ts +60 -0
  297. package/dist/fiscal/ingestion/direction.d.ts.map +1 -0
  298. package/dist/fiscal/ingestion/direction.js +32 -0
  299. package/dist/fiscal/ingestion/direction.js.map +1 -0
  300. package/dist/fiscal/ingestion/nfse-adn.d.ts +91 -0
  301. package/dist/fiscal/ingestion/nfse-adn.d.ts.map +1 -0
  302. package/dist/fiscal/ingestion/nfse-adn.js +222 -0
  303. package/dist/fiscal/ingestion/nfse-adn.js.map +1 -0
  304. package/dist/fiscal/ingestion/pipeline.d.ts +168 -0
  305. package/dist/fiscal/ingestion/pipeline.d.ts.map +1 -0
  306. package/dist/fiscal/ingestion/pipeline.js +699 -0
  307. package/dist/fiscal/ingestion/pipeline.js.map +1 -0
  308. package/dist/fiscal/ingestion/provider.d.ts +206 -0
  309. package/dist/fiscal/ingestion/provider.d.ts.map +1 -0
  310. package/dist/fiscal/ingestion/provider.js +47 -0
  311. package/dist/fiscal/ingestion/provider.js.map +1 -0
  312. package/dist/fiscal/ingestion/repository.d.ts +82 -0
  313. package/dist/fiscal/ingestion/repository.d.ts.map +1 -0
  314. package/dist/fiscal/ingestion/repository.js +127 -0
  315. package/dist/fiscal/ingestion/repository.js.map +1 -0
  316. package/dist/fiscal/ingestion/synthetic-provider.d.ts +92 -0
  317. package/dist/fiscal/ingestion/synthetic-provider.d.ts.map +1 -0
  318. package/dist/fiscal/ingestion/synthetic-provider.js +99 -0
  319. package/dist/fiscal/ingestion/synthetic-provider.js.map +1 -0
  320. package/dist/fiscal/ingestion/synthetic-transport-types.d.ts +19 -0
  321. package/dist/fiscal/ingestion/synthetic-transport-types.d.ts.map +1 -0
  322. package/dist/fiscal/ingestion/synthetic-transport-types.js +9 -0
  323. package/dist/fiscal/ingestion/synthetic-transport-types.js.map +1 -0
  324. package/dist/fiscal/ingestion/synthetic-transport.d.ts +55 -0
  325. package/dist/fiscal/ingestion/synthetic-transport.d.ts.map +1 -0
  326. package/dist/fiscal/ingestion/synthetic-transport.js +57 -0
  327. package/dist/fiscal/ingestion/synthetic-transport.js.map +1 -0
  328. package/dist/fiscal/ingestion/xml-reader.d.ts +55 -0
  329. package/dist/fiscal/ingestion/xml-reader.d.ts.map +1 -0
  330. package/dist/fiscal/ingestion/xml-reader.js +112 -0
  331. package/dist/fiscal/ingestion/xml-reader.js.map +1 -0
  332. package/dist/fiscal/repository.d.ts +220 -0
  333. package/dist/fiscal/repository.d.ts.map +1 -0
  334. package/dist/fiscal/repository.js +449 -0
  335. package/dist/fiscal/repository.js.map +1 -0
  336. package/dist/fiscal/sync/circuit.d.ts +86 -0
  337. package/dist/fiscal/sync/circuit.d.ts.map +1 -0
  338. package/dist/fiscal/sync/circuit.js +118 -0
  339. package/dist/fiscal/sync/circuit.js.map +1 -0
  340. package/dist/fiscal/sync/intervention.d.ts +81 -0
  341. package/dist/fiscal/sync/intervention.d.ts.map +1 -0
  342. package/dist/fiscal/sync/intervention.js +135 -0
  343. package/dist/fiscal/sync/intervention.js.map +1 -0
  344. package/dist/fiscal/sync/lease.d.ts +118 -0
  345. package/dist/fiscal/sync/lease.d.ts.map +1 -0
  346. package/dist/fiscal/sync/lease.js +139 -0
  347. package/dist/fiscal/sync/lease.js.map +1 -0
  348. package/dist/fiscal/sync/observability.d.ts +148 -0
  349. package/dist/fiscal/sync/observability.d.ts.map +1 -0
  350. package/dist/fiscal/sync/observability.js +239 -0
  351. package/dist/fiscal/sync/observability.js.map +1 -0
  352. package/dist/fiscal/sync/orchestrator.d.ts +132 -0
  353. package/dist/fiscal/sync/orchestrator.d.ts.map +1 -0
  354. package/dist/fiscal/sync/orchestrator.js +487 -0
  355. package/dist/fiscal/sync/orchestrator.js.map +1 -0
  356. package/dist/fiscal/sync/policy.d.ts +87 -0
  357. package/dist/fiscal/sync/policy.d.ts.map +1 -0
  358. package/dist/fiscal/sync/policy.js +136 -0
  359. package/dist/fiscal/sync/policy.js.map +1 -0
  360. package/dist/fiscal/sync/reprocess.d.ts +76 -0
  361. package/dist/fiscal/sync/reprocess.d.ts.map +1 -0
  362. package/dist/fiscal/sync/reprocess.js +237 -0
  363. package/dist/fiscal/sync/reprocess.js.map +1 -0
  364. package/dist/fiscal/sync/retry.d.ts +82 -0
  365. package/dist/fiscal/sync/retry.d.ts.map +1 -0
  366. package/dist/fiscal/sync/retry.js +176 -0
  367. package/dist/fiscal/sync/retry.js.map +1 -0
  368. package/dist/fiscal/sync/secret-boundary.d.ts +169 -0
  369. package/dist/fiscal/sync/secret-boundary.d.ts.map +1 -0
  370. package/dist/fiscal/sync/secret-boundary.js +116 -0
  371. package/dist/fiscal/sync/secret-boundary.js.map +1 -0
  372. package/dist/fiscal/transport/https.d.ts +86 -0
  373. package/dist/fiscal/transport/https.d.ts.map +1 -0
  374. package/dist/fiscal/transport/https.js +303 -0
  375. package/dist/fiscal/transport/https.js.map +1 -0
  376. package/dist/fiscal/transport/synthetic-tls.d.ts +80 -0
  377. package/dist/fiscal/transport/synthetic-tls.d.ts.map +1 -0
  378. package/dist/fiscal/transport/synthetic-tls.js +323 -0
  379. package/dist/fiscal/transport/synthetic-tls.js.map +1 -0
  380. package/dist/fiscal/transport/types.d.ts +134 -0
  381. package/dist/fiscal/transport/types.d.ts.map +1 -0
  382. package/dist/fiscal/transport/types.js +88 -0
  383. package/dist/fiscal/transport/types.js.map +1 -0
  384. package/dist/import/br-documents.d.ts +26 -0
  385. package/dist/import/br-documents.d.ts.map +1 -0
  386. package/dist/import/br-documents.js +78 -0
  387. package/dist/import/br-documents.js.map +1 -0
  388. package/dist/import/clients-import.d.ts +122 -4
  389. package/dist/import/clients-import.d.ts.map +1 -1
  390. package/dist/import/clients-import.js +341 -41
  391. package/dist/import/clients-import.js.map +1 -1
  392. package/dist/index.d.ts +115 -11
  393. package/dist/index.d.ts.map +1 -1
  394. package/dist/index.js +100 -7
  395. package/dist/index.js.map +1 -1
  396. package/dist/legal/documents.d.ts +12 -1
  397. package/dist/legal/documents.d.ts.map +1 -1
  398. package/dist/legal/documents.js +98 -14
  399. package/dist/legal/documents.js.map +1 -1
  400. package/dist/legal/index.d.ts +1 -1
  401. package/dist/legal/index.d.ts.map +1 -1
  402. package/dist/legal/index.js +1 -1
  403. package/dist/legal/index.js.map +1 -1
  404. package/dist/legal/types.d.ts +37 -2
  405. package/dist/legal/types.d.ts.map +1 -1
  406. package/dist/legal/types.js.map +1 -1
  407. package/dist/onboarding/persistence.d.ts +10 -1
  408. package/dist/onboarding/persistence.d.ts.map +1 -1
  409. package/dist/onboarding/persistence.js +4 -4
  410. package/dist/onboarding/persistence.js.map +1 -1
  411. package/dist/pilot/go-live-checklist.d.ts +41 -0
  412. package/dist/pilot/go-live-checklist.d.ts.map +1 -0
  413. package/dist/pilot/go-live-checklist.js +209 -0
  414. package/dist/pilot/go-live-checklist.js.map +1 -0
  415. package/dist/pilot/milestone.d.ts +56 -0
  416. package/dist/pilot/milestone.d.ts.map +1 -0
  417. package/dist/pilot/milestone.js +74 -0
  418. package/dist/pilot/milestone.js.map +1 -0
  419. package/dist/platform/capabilities.d.ts +88 -0
  420. package/dist/platform/capabilities.d.ts.map +1 -0
  421. package/dist/platform/capabilities.js +140 -0
  422. package/dist/platform/capabilities.js.map +1 -0
  423. package/dist/platform/job-contract.d.ts +232 -0
  424. package/dist/platform/job-contract.d.ts.map +1 -0
  425. package/dist/platform/job-contract.js +403 -0
  426. package/dist/platform/job-contract.js.map +1 -0
  427. package/dist/rbac/catalog.d.ts.map +1 -1
  428. package/dist/rbac/catalog.js +34 -0
  429. package/dist/rbac/catalog.js.map +1 -1
  430. package/dist/subscription-billing/index.d.ts +6 -5
  431. package/dist/subscription-billing/index.d.ts.map +1 -1
  432. package/dist/subscription-billing/index.js +3 -3
  433. package/dist/subscription-billing/index.js.map +1 -1
  434. package/dist/subscription-billing/service.d.ts +21 -0
  435. package/dist/subscription-billing/service.d.ts.map +1 -1
  436. package/dist/subscription-billing/service.js +90 -15
  437. package/dist/subscription-billing/service.js.map +1 -1
  438. package/dist/tenancy/features.d.ts +69 -0
  439. package/dist/tenancy/features.d.ts.map +1 -0
  440. package/dist/tenancy/features.js +123 -0
  441. package/dist/tenancy/features.js.map +1 -0
  442. package/dist/tenancy/settings.d.ts +63 -0
  443. package/dist/tenancy/settings.d.ts.map +1 -0
  444. package/dist/tenancy/settings.js +218 -0
  445. package/dist/tenancy/settings.js.map +1 -0
  446. package/dist/users/repository.d.ts +16 -1
  447. package/dist/users/repository.d.ts.map +1 -1
  448. package/dist/users/repository.js +24 -1
  449. package/dist/users/repository.js.map +1 -1
  450. package/package.json +9 -2
  451. package/src/db/migrations/0045_role_write_scope.sql +122 -0
  452. package/src/db/migrations/0046_pilot_activation_model.sql +184 -0
  453. package/src/db/migrations/0047_recipient_clearance.sql +89 -0
  454. package/src/db/migrations/0048_item_type_note.sql +16 -0
  455. package/src/db/migrations/0049_national_fiscal_engine.sql +279 -0
  456. package/src/db/migrations/0050_fiscal_vocabulary_readonly.sql +29 -0
  457. package/src/db/migrations/0051_seed_rules_from_catalog.sql +72 -0
  458. package/src/db/migrations/0052_fiscal_rule_delete_scope.sql +57 -0
  459. package/src/db/migrations/0053_rule_validity_lower_bound.sql +44 -0
  460. package/src/db/migrations/0054_tenant_profile_and_rule_source.sql +89 -0
  461. package/src/db/migrations/0055_job_capability_contract.sql +300 -0
  462. package/src/db/migrations/0056_fiscal_document_ingestion.sql +337 -0
  463. package/src/db/migrations/0057_fiscal_pending_event_inbox.sql +228 -0
  464. package/src/db/migrations/0058_fiscal_operational_engine.sql +516 -0
  465. package/src/db/migrations/0059_fiscal_contract_version.sql +59 -0
@@ -0,0 +1,279 @@
1
+ -- 0049 — a fundação nacional do motor fiscal.
2
+ --
3
+ -- ═══ A decisão de modelagem que organiza tudo ═══════════════════════════════
4
+ --
5
+ -- Hoje `recurring_item_type` responde duas perguntas diferentes na mesma linha:
6
+ --
7
+ -- "o que é esta obrigação?" → DAS, ISS, eSocial. Nacional e estável.
8
+ -- "para quem, quando e como vence?" → varia por UF, por município e no tempo.
9
+ --
10
+ -- Enquanto as duas moram juntas, o índice único em `(key)` permite UMA linha
11
+ -- por chave, e daí saem as três limitações que a auditoria mediu: o ISS de
12
+ -- Goiânia e o de São Paulo não coexistem, duas versões da mesma regra não
13
+ -- coexistem, e a aplicabilidade só sabe olhar regime.
14
+ --
15
+ -- Esta migration separa as duas perguntas:
16
+ --
17
+ -- `recurring_item_type` → a IDENTIDADE. Continua como está. Nada quebra.
18
+ -- `fiscal_rule` → a REGRA: jurisdição + vigência + versão +
19
+ -- condições + vencimento.
20
+ --
21
+ -- Um tipo de item passa a ter N regras: uma federal, uma por UF, uma por
22
+ -- município, e mais de uma no tempo. É o que abrangência nacional exige, e é
23
+ -- aditivo — nenhuma linha existente é reescrita.
24
+ --
25
+ -- ═══ O que esta migration NÃO faz ══════════════════════════════════════════
26
+ --
27
+ -- Não cataloga regra nenhuma do Brasil. Ela cria a capacidade; o conteúdo
28
+ -- entra depois, com governança. Os 17 seeds atuais são migrados na 0050 SEM
29
+ -- ganhar precisão que não têm.
30
+
31
+ -- ── 1 · Vocabulário do perfil fiscal ───────────────────────────────────────
32
+ --
33
+ -- Registro de atributos, e não colunas em `client`.
34
+ --
35
+ -- A alternativa seria `has_employees`, `icms_taxpayer`, `iss_taxpayer`,
36
+ -- `ipi_taxpayer`… uma coluna por pergunta fiscal. Isso não escala: cada UF e
37
+ -- cada segmento acrescenta perguntas, e a tabela de cliente viraria uma
38
+ -- estrutura rígida impossível de evoluir — exatamente o que a premissa pede
39
+ -- para evitar.
40
+ --
41
+ -- Com um REGISTRO, acrescentar um atributo é INSERT, não migration. E a FK
42
+ -- impede erro de digitação virar atributo novo em silêncio.
43
+
44
+ CREATE TABLE IF NOT EXISTS fiscal_attribute_definition (
45
+ key text PRIMARY KEY,
46
+ label text NOT NULL,
47
+ description text,
48
+ value_type text NOT NULL CHECK (value_type IN ('boolean', 'text', 'enum')),
49
+ -- Para `enum`: os valores aceitos. Para os demais, `null`.
50
+ allowed_values jsonb,
51
+ created_at timestamptz NOT NULL DEFAULT now(),
52
+ CHECK ((value_type = 'enum') = (allowed_values IS NOT NULL))
53
+ );
54
+
55
+ COMMENT ON TABLE fiscal_attribute_definition IS
56
+ 'Vocabulário GLOBAL do perfil fiscal. Acrescentar atributo é INSERT, não migration — é o que permite o modelo evoluir sem alterar a tabela de cliente.';
57
+
58
+ INSERT INTO fiscal_attribute_definition (key, label, description, value_type, allowed_values) VALUES
59
+ ('has_employees', 'Possui empregados',
60
+ 'Decide a aplicabilidade das obrigações trabalhistas. A AUSÊNCIA deste dado não é "não": é desconhecido, e o motor devolve INSUFFICIENT_DATA.',
61
+ 'boolean', NULL),
62
+ ('icms_taxpayer', 'Contribuinte de ICMS', NULL, 'boolean', NULL),
63
+ ('ipi_taxpayer', 'Contribuinte de IPI', NULL, 'boolean', NULL),
64
+ ('iss_taxpayer', 'Contribuinte de ISS', NULL, 'boolean', NULL),
65
+ ('activity_segment', 'Segmento de atividade', NULL,
66
+ 'enum', '["comercio","industria","servicos","misto"]'::jsonb),
67
+ ('cnae_primary', 'CNAE principal', 'Código, sem interpretação pelo motor nesta fase.', 'text', NULL),
68
+ ('state_registration', 'Inscrição estadual', NULL, 'text', NULL),
69
+ ('municipal_registration', 'Inscrição municipal', NULL, 'text', NULL)
70
+ ON CONFLICT (key) DO NOTHING;
71
+
72
+ -- ── 2 · Perfil fiscal do cliente ───────────────────────────────────────────
73
+ --
74
+ -- Ausência de linha = atributo DESCONHECIDO, e é distinto de `false`. É a
75
+ -- distinção que sustenta o `INSUFFICIENT_DATA` do motor: um cliente sobre o
76
+ -- qual ninguém disse se tem empregados não pode receber eSocial nem ser
77
+ -- declarado isento dele.
78
+
79
+ CREATE TABLE IF NOT EXISTS client_fiscal_attribute (
80
+ id uuid PRIMARY KEY,
81
+ tenant_id uuid NOT NULL REFERENCES tenant(id),
82
+ client_id uuid NOT NULL,
83
+ attribute_key text NOT NULL REFERENCES fiscal_attribute_definition(key),
84
+ value_bool boolean,
85
+ value_text text,
86
+ source text,
87
+ updated_by uuid REFERENCES "user"(id),
88
+ created_at timestamptz NOT NULL DEFAULT now(),
89
+ updated_at timestamptz NOT NULL DEFAULT now(),
90
+ CONSTRAINT client_fiscal_attribute_tenant_id_uq UNIQUE (tenant_id, id),
91
+ FOREIGN KEY (tenant_id, client_id) REFERENCES client (tenant_id, id),
92
+ -- Exatamente um valor. Nenhum seria linha sem informação; dois seriam duas
93
+ -- respostas para a mesma pergunta.
94
+ CHECK ((value_bool IS NOT NULL)::int + (value_text IS NOT NULL)::int = 1)
95
+ );
96
+
97
+ CREATE UNIQUE INDEX IF NOT EXISTS client_fiscal_attribute_uq
98
+ ON client_fiscal_attribute (tenant_id, client_id, attribute_key);
99
+
100
+ ALTER TABLE client_fiscal_attribute ENABLE ROW LEVEL SECURITY;
101
+ ALTER TABLE client_fiscal_attribute FORCE ROW LEVEL SECURITY;
102
+ CREATE POLICY client_fiscal_attribute_tenant_isolation ON client_fiscal_attribute
103
+ USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
104
+ WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
105
+
106
+ -- Código IBGE do município: o identificador canônico.
107
+ --
108
+ -- `client.municipality` é texto livre e serve para a tela. Casar regra
109
+ -- municipal por texto livre falharia no primeiro "Goiania" sem acento. O
110
+ -- código é opcional: sem ele, regra municipal devolve INSUFFICIENT_DATA em vez
111
+ -- de casar por aproximação.
112
+ ALTER TABLE client ADD COLUMN IF NOT EXISTS municipality_ibge_code text;
113
+
114
+ DO $$
115
+ BEGIN
116
+ IF NOT EXISTS (SELECT FROM pg_constraint WHERE conname = 'client_ibge_format') THEN
117
+ ALTER TABLE client ADD CONSTRAINT client_ibge_format
118
+ CHECK (municipality_ibge_code IS NULL OR municipality_ibge_code ~ '^[0-9]{7}$');
119
+ END IF;
120
+ END $$;
121
+
122
+ -- ── 3 · A regra fiscal versionada ──────────────────────────────────────────
123
+
124
+ CREATE TABLE IF NOT EXISTS fiscal_rule (
125
+ id uuid PRIMARY KEY,
126
+ -- NULL = regra GLOBAL do produto. NOT NULL = regra do próprio escritório.
127
+ -- Mesmo padrão de `recurring_item_type` e `role`: ler o global é direito de
128
+ -- todos; escrevê-lo, de ninguém que opere como tenant.
129
+ tenant_id uuid REFERENCES tenant(id),
130
+ item_type_id uuid NOT NULL REFERENCES recurring_item_type(id),
131
+
132
+ -- ── jurisdição ──────────────────────────────────────────────────────────
133
+ jurisdiction_scope text NOT NULL CHECK (jurisdiction_scope IN ('federal', 'state', 'municipal')),
134
+ jurisdiction_uf text CHECK (jurisdiction_uf IS NULL OR jurisdiction_uf ~ '^[A-Z]{2}$'),
135
+ jurisdiction_city_ibge text CHECK (jurisdiction_city_ibge IS NULL OR jurisdiction_city_ibge ~ '^[0-9]{7}$'),
136
+ -- A jurisdição precisa ser COMPLETA para o seu nível. Uma regra "estadual"
137
+ -- sem UF não é uma regra: é um marcador que casaria com o país inteiro.
138
+ CHECK (
139
+ (jurisdiction_scope = 'federal' AND jurisdiction_uf IS NULL AND jurisdiction_city_ibge IS NULL) OR
140
+ (jurisdiction_scope = 'state' AND jurisdiction_uf IS NOT NULL AND jurisdiction_city_ibge IS NULL) OR
141
+ (jurisdiction_scope = 'municipal' AND jurisdiction_uf IS NOT NULL AND jurisdiction_city_ibge IS NOT NULL)
142
+ ),
143
+
144
+ -- ── vigência e versão ───────────────────────────────────────────────────
145
+ version int NOT NULL DEFAULT 1 CHECK (version > 0),
146
+ valid_from date NOT NULL,
147
+ valid_until date,
148
+ CHECK (valid_until IS NULL OR valid_until >= valid_from),
149
+
150
+ status text NOT NULL DEFAULT 'pending_validation'
151
+ CHECK (status IN ('not_configured', 'pending_validation', 'validated', 'expired', 'disabled')),
152
+
153
+ -- ── conteúdo ────────────────────────────────────────────────────────────
154
+ -- AST declarativa. Interpretada por código tipado, NUNCA avaliada como
155
+ -- expressão: nada aqui vira `eval`, SQL ou função.
156
+ conditions jsonb NOT NULL DEFAULT '{"op":"always"}'::jsonb,
157
+ due_rule jsonb,
158
+
159
+ -- ── procedência ─────────────────────────────────────────────────────────
160
+ source_reference text,
161
+ validated_by uuid REFERENCES "user"(id),
162
+ validated_at timestamptz,
163
+ note text,
164
+
165
+ created_at timestamptz NOT NULL DEFAULT now(),
166
+ updated_at timestamptz NOT NULL DEFAULT now(),
167
+ deleted_at timestamptz,
168
+
169
+ CONSTRAINT fiscal_rule_tenant_id_uq UNIQUE (tenant_id, id),
170
+ -- Uma regra `validated` sem quem validou é uma afirmação sem autor.
171
+ CHECK ((status <> 'validated') OR (validated_at IS NOT NULL AND validated_by IS NOT NULL)),
172
+ -- `not_configured` é o estado honesto de quem não tem vencimento definido.
173
+ -- Uma regra validada SEM vencimento produziria obrigação sem data.
174
+ CHECK ((status <> 'validated') OR due_rule IS NOT NULL)
175
+ );
176
+
177
+ -- Versões da mesma regra não se sobrepõem: uma só vigente por jurisdição.
178
+ -- Mesmo padrão que `accounting_regime` já provou para o regime do cliente.
179
+ CREATE UNIQUE INDEX IF NOT EXISTS fiscal_rule_current_uq
180
+ ON fiscal_rule (
181
+ coalesce(tenant_id::text, '-'), item_type_id, jurisdiction_scope,
182
+ coalesce(jurisdiction_uf, '-'), coalesce(jurisdiction_city_ibge, '-')
183
+ )
184
+ WHERE valid_until IS NULL AND deleted_at IS NULL;
185
+
186
+ CREATE UNIQUE INDEX IF NOT EXISTS fiscal_rule_version_uq
187
+ ON fiscal_rule (
188
+ coalesce(tenant_id::text, '-'), item_type_id, jurisdiction_scope,
189
+ coalesce(jurisdiction_uf, '-'), coalesce(jurisdiction_city_ibge, '-'), version
190
+ )
191
+ WHERE deleted_at IS NULL;
192
+
193
+ -- Pré-filtragem: a engine busca por jurisdição + vigência antes de avaliar
194
+ -- condição nenhuma. Sem este índice, avaliar a carteira exigiria varrer o
195
+ -- catálogo inteiro por cliente.
196
+ CREATE INDEX IF NOT EXISTS fiscal_rule_lookup_idx
197
+ ON fiscal_rule (jurisdiction_scope, jurisdiction_uf, jurisdiction_city_ibge, valid_from)
198
+ WHERE deleted_at IS NULL;
199
+ CREATE INDEX IF NOT EXISTS fiscal_rule_item_idx
200
+ ON fiscal_rule (item_type_id, valid_from) WHERE deleted_at IS NULL;
201
+
202
+ ALTER TABLE fiscal_rule ENABLE ROW LEVEL SECURITY;
203
+ ALTER TABLE fiscal_rule FORCE ROW LEVEL SECURITY;
204
+
205
+ -- Leitura: a regra global e as do próprio escritório.
206
+ -- Escrita: SOMENTE as do próprio escritório.
207
+ --
208
+ -- O `WITH CHECK` sem o ramo `IS NULL` é a lição da 0045: com ele, qualquer
209
+ -- tenant forjaria regra fiscal GLOBAL — que vale para todos os escritórios do
210
+ -- país. É a escalada mais cara que este schema comporta.
211
+ CREATE POLICY fiscal_rule_visibility ON fiscal_rule
212
+ USING (tenant_id IS NULL OR tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
213
+ WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
214
+
215
+ DO $$
216
+ DECLARE owner_role text;
217
+ BEGIN
218
+ SELECT tableowner INTO owner_role FROM pg_tables
219
+ WHERE schemaname = 'public' AND tablename = 'fiscal_rule';
220
+ IF owner_role IS NULL THEN
221
+ RAISE EXCEPTION 'fiscal_rule sem dono identificável — abortando';
222
+ END IF;
223
+ -- FORCE RLS vale para o dono; o provisionamento do catálogo global roda sem
224
+ -- tenant no contexto e precisa de política nominal. Padrão da 0042/0045.
225
+ EXECUTE format(
226
+ 'CREATE POLICY fiscal_rule_system_provisioning ON fiscal_rule FOR ALL TO %I USING (true) WITH CHECK (true)',
227
+ owner_role);
228
+ END $$;
229
+
230
+ COMMENT ON POLICY fiscal_rule_visibility ON fiscal_rule IS
231
+ 'Leitura: regra global + as do tenant. Escrita: SOMENTE do tenant. O ramo IS NULL fora do WITH CHECK impede forjar regra fiscal nacional (lição do P0-A, Fase 4).';
232
+
233
+ -- ── 4 · Política operacional do escritório ─────────────────────────────────
234
+ --
235
+ -- Separa REGRA LEGAL de PROCEDIMENTO DO ESCRITÓRIO.
236
+ --
237
+ -- O prazo legal do DAS é do país. O prazo em que o escritório quer os
238
+ -- documentos do cliente na mão é dele. Enquanto os dois moram no mesmo campo,
239
+ -- ajustar o procedimento interno reescreve a regra legal — em silêncio, e para
240
+ -- todo mundo que enxerga aquela linha.
241
+
242
+ CREATE TABLE IF NOT EXISTS tenant_rule_policy (
243
+ id uuid PRIMARY KEY,
244
+ tenant_id uuid NOT NULL REFERENCES tenant(id),
245
+ item_type_id uuid NOT NULL REFERENCES recurring_item_type(id),
246
+ -- Dias ANTES do vencimento legal em que o escritório quer a coisa pronta.
247
+ -- Não altera o vencimento legal: acrescenta um prazo interno ao lado dele.
248
+ internal_lead_days int CHECK (internal_lead_days IS NULL OR internal_lead_days BETWEEN 0 AND 90),
249
+ enabled boolean NOT NULL DEFAULT true,
250
+ note text,
251
+ updated_by uuid REFERENCES "user"(id),
252
+ created_at timestamptz NOT NULL DEFAULT now(),
253
+ updated_at timestamptz NOT NULL DEFAULT now(),
254
+ CONSTRAINT tenant_rule_policy_tenant_id_uq UNIQUE (tenant_id, id)
255
+ );
256
+
257
+ CREATE UNIQUE INDEX IF NOT EXISTS tenant_rule_policy_uq
258
+ ON tenant_rule_policy (tenant_id, item_type_id);
259
+
260
+ ALTER TABLE tenant_rule_policy ENABLE ROW LEVEL SECURITY;
261
+ ALTER TABLE tenant_rule_policy FORCE ROW LEVEL SECURITY;
262
+ CREATE POLICY tenant_rule_policy_tenant_isolation ON tenant_rule_policy
263
+ USING (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid)
264
+ WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant', true), '')::uuid);
265
+
266
+ COMMENT ON TABLE tenant_rule_policy IS
267
+ 'Procedimento do escritório, ao LADO da regra legal e nunca por cima dela. Prazo interno não é prazo legal.';
268
+
269
+ -- ── 5 · Preservação histórica ──────────────────────────────────────────────
270
+ --
271
+ -- A instância já congela `label` e `due_date`. Falta saber QUAL versão da
272
+ -- regra produziu aquela data — sem isso, uma V2 publicada amanhã faz a
273
+ -- obrigação de ontem parecer ter nascido de uma regra que não existia.
274
+
275
+ ALTER TABLE recurring_instance ADD COLUMN IF NOT EXISTS fiscal_rule_id uuid REFERENCES fiscal_rule(id);
276
+ ALTER TABLE recurring_instance ADD COLUMN IF NOT EXISTS fiscal_rule_version int;
277
+
278
+ COMMENT ON COLUMN recurring_instance.fiscal_rule_id IS
279
+ 'Versão EXATA da regra que gerou esta obrigação. Publicar uma V2 não altera o que já foi gerado sob a V1.';
@@ -0,0 +1,29 @@
1
+ -- 0050 — o vocabulário do perfil fiscal é lido pelo runtime, nunca escrito.
2
+ --
3
+ -- Esta migration existe separada da 0049 por uma razão de processo, e vale
4
+ -- registrar: eu havia acrescentado este bloco ao fim da 0049 depois de ela já
5
+ -- ter sido aplicada. O runner recusou — migrations são imutáveis, e a checagem
6
+ -- de hash existe exatamente para impedir que o que rodou num ambiente seja
7
+ -- diferente do que roda no próximo.
8
+ --
9
+ -- ── A barreira ─────────────────────────────────────────────────────────────
10
+ --
11
+ -- `fiscal_attribute_definition` é catálogo GLOBAL, sem `tenant_id`. Não há RLS
12
+ -- que o proteja, porque não há linha de ninguém: a barreira só pode ser o
13
+ -- privilégio.
14
+ --
15
+ -- O runtime lê o vocabulário a cada avaliação de aplicabilidade e nunca o
16
+ -- escreve. Um tenant capaz de inserir atributo aqui poderia criar um atributo
17
+ -- que nenhuma regra usa (inócuo) ou — pior — apagar um que as regras de todos
18
+ -- os escritórios usam, derrubando a avaliação do país inteiro por FK.
19
+ --
20
+ -- Repetido em `migrate.ts` no mesmo bloco de `role` e `audit_log`: o GRANT da
21
+ -- allowlist é amplo por construção e devolveria a escrita no deploy seguinte.
22
+ -- Foi o defeito que a Fase 3 encontrou ao separar GRANT de hardening.
23
+
24
+ DO $$
25
+ BEGIN
26
+ IF EXISTS (SELECT FROM pg_roles WHERE rolname = 'baruk_app') THEN
27
+ EXECUTE 'REVOKE INSERT, UPDATE, DELETE ON fiscal_attribute_definition FROM baruk_app';
28
+ END IF;
29
+ END $$;
@@ -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.';