@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,215 @@
1
+ import { gunzipSync } from 'node:zlib';
2
+ import { FiscalProviderError, } from '../ingestion/provider.js';
3
+ import { NFSE_ADN_LIMITS, NFSE_ADN_OFFICIAL_CODES, } from './nfse-adn-contract.js';
4
+ /**
5
+ * A resposta não corresponde ao contrato declarado.
6
+ *
7
+ * Classe `invalid` porque retentar não resolve: o formato não muda entre
8
+ * tentativas. `providerCode` é SEMPRE `PROTOCOL_CONTRACT_MISMATCH` — um código
9
+ * único é o que permite ao painel perguntar "o contrato quebrou?" com uma
10
+ * comparação de igualdade. O detalhe fica em `reason`, que é enumerado e não
11
+ * carrega um byte do corpo recebido: um corpo hostil não escreve na nossa trilha.
12
+ */
13
+ export class AdnContractMismatchError extends FiscalProviderError {
14
+ reason;
15
+ profileId;
16
+ constructor(reason, profileId) {
17
+ super('invalid', `resposta do ADN não corresponde ao perfil ${profileId} (${reason})`, 'PROTOCOL_CONTRACT_MISMATCH');
18
+ this.reason = reason;
19
+ this.profileId = profileId;
20
+ this.name = 'AdnContractMismatchError';
21
+ }
22
+ }
23
+ /** Base64 canônico. `Buffer.from(x,'base64')` ignora lixo em silêncio — este não. */
24
+ const BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
25
+ /** Assinatura do gzip (RFC 1952 §2.3.1): `1f 8b`. Dois bytes, sem ambiguidade. */
26
+ const GZIP_MAGIC = [0x1f, 0x8b];
27
+ /**
28
+ * Lê o envelope. Devolve lote (possivelmente vazio e RECONHECIDO), ou lança.
29
+ *
30
+ * Nunca devolve `documents: []` para uma resposta que não entendeu. Essa é a
31
+ * invariante, e o teste de mutação da Fase 3 a exercita reintroduzindo o
32
+ * comportamento antigo e exigindo que a suíte fique vermelha.
33
+ */
34
+ export function readAdnEnvelope(body, options) {
35
+ const { profile, fromNsu } = options;
36
+ const maxBytes = options.maxResponseBytes ?? NFSE_ADN_LIMITS.maxResponseBytes.value;
37
+ const maxDoc = options.maxDecompressedBytesPerDocument ??
38
+ NFSE_ADN_LIMITS.maxDecompressedBytesPerDocument.value;
39
+ const maxLote = options.maxDecompressedBytesPerBatch ?? NFSE_ADN_LIMITS.maxDecompressedBytesPerBatch.value;
40
+ const maxItens = options.maxDocumentsPerBatch ?? NFSE_ADN_LIMITS.maxDocumentsPerBatch.value;
41
+ // A anotação de tipo explícita não é decoração: sem ela o TypeScript não
42
+ // propaga o `never` de uma arrow function, e todo `if (...) recusa(...)`
43
+ // deixaria de estreitar o tipo depois — obrigando a um `return` ou a um `!`
44
+ // em cada ponto, que é exatamente onde um dia alguém erra.
45
+ const recusa = (r) => {
46
+ throw new AdnContractMismatchError(r, profile.id);
47
+ };
48
+ if (body.byteLength > maxBytes)
49
+ recusa('RESPONSE_TOO_LARGE');
50
+ if (body.byteLength === 0)
51
+ recusa('BODY_EMPTY');
52
+ const texto = Buffer.from(body).toString('utf8').trim();
53
+ // Página de erro de proxy, portal de captura, HTML de WAF. Todos começam com
54
+ // `<`, e todos seriam "JSON inválido" — um diagnóstico que manda a pessoa
55
+ // olhar o lugar errado. Nomear o caso aponta para a rede, não para o parser.
56
+ if (texto.startsWith('<'))
57
+ recusa('MARKUP_INSTEAD_OF_JSON');
58
+ let json;
59
+ try {
60
+ json = JSON.parse(texto);
61
+ }
62
+ catch {
63
+ recusa('NOT_JSON');
64
+ }
65
+ if (json === null || typeof json !== 'object' || Array.isArray(json))
66
+ recusa('NOT_OBJECT');
67
+ const raiz = json;
68
+ // ── Rejeição RECONHECIDA ────────────────────────────────────────────────
69
+ //
70
+ // Antes de exigir o lote: uma rejeição legítima do ADN não traz lote nenhum,
71
+ // e cobrá-lo dela transformaria "seu cliente não teve nota" em "o contrato
72
+ // quebrou" — o alarme mais caro que este produto poderia dar.
73
+ const codigo = leiaCodigo(raiz[profile.codeField]);
74
+ if (codigo) {
75
+ const oficial = NFSE_ADN_OFFICIAL_CODES[codigo];
76
+ if (oficial?.outcome === 'no_documents') {
77
+ return {
78
+ documents: [],
79
+ // A posição de quem não achou nada é a de onde partiu. Ver o comentário
80
+ // de `fromNsu` acima: `null` aqui faria a próxima execução recomeçar.
81
+ lastNsu: fromNsu,
82
+ maxNsu: null,
83
+ // Esgotado: o Manual dos Municípios §1.4.2.b manda esperar uma hora
84
+ // "caso receba a indicação que não existem mais documentos".
85
+ exhausted: true,
86
+ providerStatus: codigo,
87
+ };
88
+ }
89
+ if (oficial) {
90
+ throw new FiscalProviderError(oficial.errorClass ?? 'unknown', `ADN recusou: ${oficial.meaning}`, codigo);
91
+ }
92
+ // Código do ADN que não está no nosso mapa. NÃO é lote vazio, e NÃO é
93
+ // `invalid`: o governo pode ter acrescentado um código sem mudar o
94
+ // envelope. `unknown` é tratado como transitório com teto pelo motor —
95
+ // errar para "tente de novo com espera" custa latência; errar para "está
96
+ // tudo bem, zero documentos" custa uma fiscalização.
97
+ throw new FiscalProviderError('unknown', 'ADN devolveu código não catalogado', codigo);
98
+ }
99
+ // ── Lote ────────────────────────────────────────────────────────────────
100
+ if (!(profile.batchField in raiz))
101
+ recusa('BATCH_FIELD_MISSING');
102
+ const lote = raiz[profile.batchField];
103
+ if (!Array.isArray(lote))
104
+ recusa('BATCH_NOT_ARRAY');
105
+ const itens = lote;
106
+ // O teto de 50 é oficial. Um lote maior significa que estamos falando com
107
+ // algo que não é o ADN — ou que o contrato mudou. Nos dois casos, parar.
108
+ if (itens.length > maxItens)
109
+ recusa('BATCH_OVER_OFFICIAL_LIMIT');
110
+ const documents = [];
111
+ let descompactadoNoLote = 0;
112
+ for (const item of itens) {
113
+ if (item === null || typeof item !== 'object' || Array.isArray(item))
114
+ recusa('ITEM_NOT_OBJECT');
115
+ const linha = item;
116
+ const nsu = leiaNsu(linha[profile.itemNsuField]);
117
+ if (nsu === null)
118
+ recusa('ITEM_NSU_INVALID');
119
+ const conteudo = linha[profile.itemContentField];
120
+ if (typeof conteudo !== 'string' || conteudo.length === 0)
121
+ recusa('ITEM_CONTENT_MISSING');
122
+ if (!BASE64.test(conteudo))
123
+ recusa('ITEM_CONTENT_NOT_BASE64');
124
+ const bytes = Buffer.from(conteudo, 'base64');
125
+ let raw;
126
+ if (profile.contentEncoding === 'gzip+base64') {
127
+ // A verificação da assinatura vem ANTES da descompressão, e substitui o
128
+ // `try/catch` que virava fallback. Sem ela, "não é gzip" e "é gzip
129
+ // corrompido" chegam pelo mesmo caminho — e o antigo `catch` respondia
130
+ // aos dois tratando os bytes como XML.
131
+ if (bytes.length < 2 || bytes[0] !== GZIP_MAGIC[0] || bytes[1] !== GZIP_MAGIC[1]) {
132
+ recusa('ITEM_CONTENT_NOT_GZIP');
133
+ }
134
+ try {
135
+ // `maxOutputLength` é a defesa contra bomba de descompressão: o zlib
136
+ // aborta ao ultrapassar, em vez de alocar até o processo morrer.
137
+ raw = new Uint8Array(gunzipSync(bytes, { maxOutputLength: maxDoc }));
138
+ }
139
+ catch (err) {
140
+ // O zlib distingue os dois casos, e a distinção importa: "grande demais"
141
+ // é possivelmente hostil e "corrompido" é possivelmente rede.
142
+ const code = err?.code;
143
+ if (code === 'ERR_BUFFER_TOO_LARGE')
144
+ recusa('ITEM_CONTENT_TOO_LARGE');
145
+ recusa('ITEM_CONTENT_DECOMPRESSION_FAILED');
146
+ }
147
+ }
148
+ else {
149
+ if (bytes.length > maxDoc)
150
+ recusa('ITEM_CONTENT_TOO_LARGE');
151
+ raw = new Uint8Array(bytes);
152
+ }
153
+ descompactadoNoLote += raw.byteLength;
154
+ // O teto do LOTE existe porque o produto dos tetos individuais não é um
155
+ // teto: 50 documentos de 8 MiB seriam 400 MiB perfeitamente "válidos".
156
+ if (descompactadoNoLote > maxLote)
157
+ recusa('BATCH_DECOMPRESSED_TOO_LARGE');
158
+ documents.push({ nsu, raw, mimeType: 'application/xml' });
159
+ }
160
+ const ultimo = leiaPosicao(raiz, profile.lastNsuField, recusa);
161
+ const maximo = leiaPosicao(raiz, profile.maxNsuField, recusa);
162
+ // Sem `ultNSU` declarado, a posição é a do último item — e, se nem item houve,
163
+ // é de onde partimos. Jamais `null`: ver o comentário de `fromNsu`.
164
+ const lastNsu = ultimo ?? documents.at(-1)?.nsu ?? fromNsu;
165
+ return {
166
+ documents,
167
+ lastNsu,
168
+ maxNsu: maximo,
169
+ // Esgotado é o servidor DECLARANDO que a posição alcançou o máximo
170
+ // (Manual dos Municípios §1.4.2.b: "Se o NSU informado (ultNSU) for igual ao
171
+ // maior NSU do Ambiente Nacional (maxNSU), então não existem mais
172
+ // documentos"). Nunca por lote vazio: um lote vazio no meio da faixa não
173
+ // autoriza a espera de uma hora, e tratá-lo assim atrasaria o cliente à toa.
174
+ exhausted: lastNsu !== null && maximo !== null && lastNsu === maximo,
175
+ providerStatus: null,
176
+ };
177
+ }
178
+ /**
179
+ * NSU como o contrato o define: dígitos, sem sinal, sem separador.
180
+ *
181
+ * Número JSON é aceito e normalizado para texto — o ADN pode enviá-lo como
182
+ * número, e recusá-lo seria rigor sem propósito. O que não é aceito é qualquer
183
+ * coisa que não seja uma posição: `null`, negativo, decimal, texto com letra.
184
+ * Um NSU que não é posição não pode governar cursor.
185
+ */
186
+ function leiaNsu(v) {
187
+ if (typeof v === 'number') {
188
+ return Number.isSafeInteger(v) && v >= 0 ? String(v) : null;
189
+ }
190
+ if (typeof v === 'string' && /^\d{1,20}$/.test(v))
191
+ return v;
192
+ return null;
193
+ }
194
+ /** `ultNSU`/`maxNSU`: ausente é legítimo; presente e inválido, não. */
195
+ function leiaPosicao(raiz, campo, recusa) {
196
+ if (!(campo in raiz))
197
+ return null;
198
+ const bruto = raiz[campo];
199
+ if (bruto === null || bruto === undefined)
200
+ return null;
201
+ const nsu = leiaNsu(bruto);
202
+ // Presente e ilegível é diferente de ausente: o primeiro é contrato quebrado,
203
+ // o segundo é campo opcional. Tratá-los igual perderia a quebra.
204
+ if (nsu === null)
205
+ recusa('NSU_POSITION_INVALID');
206
+ return nsu;
207
+ }
208
+ /** O código do ADN, quando a resposta é uma rejeição. `E` seguido de dígitos. */
209
+ function leiaCodigo(v) {
210
+ if (typeof v !== 'string')
211
+ return null;
212
+ const t = v.trim().toUpperCase();
213
+ return /^E\d{4}$/.test(t) ? t : null;
214
+ }
215
+ //# sourceMappingURL=nfse-adn-envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nfse-adn-envelope.js","sourceRoot":"","sources":["../../../src/fiscal/contracts/nfse-adn-envelope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import type { Tx } from '../../db/client.js';
2
+ import type { FiscalDocumentType } from '../ingestion/provider.js';
3
+ /**
4
+ * Onde a coleta automática alcança — e, principalmente, onde não sabemos.
5
+ *
6
+ * ## A frase que um produto nacional diz sem perceber
7
+ *
8
+ * "O ADN cobre a NFS-e do Brasil inteiro." É falsa. A NFS-e nacional depende de
9
+ * ADESÃO do município ao convênio; quem não aderiu continua emitindo pelo portal
10
+ * próprio, com login próprio e nenhum NSU. Vender coleta automática para um
11
+ * cliente cuja prefeitura não aderiu é prometer trabalho que ninguém fará — e o
12
+ * escritório só descobre no fechamento, quando as notas não estão lá.
13
+ *
14
+ * ## Por que a herança é PROIBIDA de cima para baixo
15
+ *
16
+ * A tentação estrutural é: "não há linha para este município, use a nacional".
17
+ * Isso é exatamente como a afirmação falsa entra no sistema — uma linha correta
18
+ * sobre o ADN respondendo uma pergunta sobre Marechal Cândido Rondon.
19
+ *
20
+ * Aqui, uma pergunta MUNICIPAL só é respondida por uma linha municipal. Sem
21
+ * medição do município, a resposta é a linha municipal PADRÃO, que diz
22
+ * `UNKNOWN`. A linha nacional responde apenas perguntas de escopo nacional.
23
+ *
24
+ * ## Cobertura técnica não é validação legal
25
+ *
26
+ * Saber COLETAR um documento não diz nada sobre a regra fiscal que se aplica a
27
+ * ele. `fiscal_rule` continua com suas 17 regras e zero validadas por pessoa, e
28
+ * nada neste módulo mexe nesse número.
29
+ */
30
+ export type CoverageStatus = 'SUPPORTED_OFFICIAL' | 'SUPPORTED_PROVIDER' | 'SUPPORTED_MANUAL_FALLBACK' | 'UNKNOWN' | 'UNSUPPORTED';
31
+ export type CoverageScope = 'national' | 'state' | 'municipal';
32
+ export interface FiscalCoverage {
33
+ id: string;
34
+ documentType: FiscalDocumentType;
35
+ jurisdictionScope: CoverageScope;
36
+ /** UF, código IBGE, ou `null` para a linha PADRÃO daquele escopo. */
37
+ jurisdictionCode: string | null;
38
+ provider: string;
39
+ coverageStatus: CoverageStatus;
40
+ automationMethod: string | null;
41
+ credentialRequirement: string;
42
+ environments: readonly string[];
43
+ fallbackType: string | null;
44
+ lastVerifiedAt: string | null;
45
+ sourceReference: string | null;
46
+ notes: string | null;
47
+ }
48
+ /** A resposta quando nem a linha padrão existe. Desconhecida, nunca coberta. */
49
+ export declare function unknownCoverage(documentType: FiscalDocumentType, scope: CoverageScope, code: string | null): FiscalCoverage;
50
+ /**
51
+ * Resolve a cobertura de uma pergunta específica.
52
+ *
53
+ * Duas etapas, e a segunda NUNCA sobe de escopo: a linha exata do código, e
54
+ * depois a linha padrão do MESMO escopo. Não há terceira etapa.
55
+ */
56
+ export declare function resolveFiscalCoverage(tx: Tx, input: {
57
+ documentType: FiscalDocumentType;
58
+ jurisdictionScope: CoverageScope;
59
+ jurisdictionCode?: string | null;
60
+ }): Promise<FiscalCoverage>;
61
+ /**
62
+ * A cobertura que vale para um CLIENTE — a pergunta que a tela realmente faz.
63
+ *
64
+ * NFS-e é municipal por natureza: quem recolhe ISS é a prefeitura. Por isso a
65
+ * pergunta pelo cliente vai ao escopo municipal, e é ali que ela encontra
66
+ * `UNKNOWN` enquanto ninguém tiver medido a adesão daquele município. NF-e e
67
+ * CT-e são de distribuição nacional, e a pergunta é nacional.
68
+ */
69
+ export declare function coverageForClient(tx: Tx, input: {
70
+ clientId: string;
71
+ documentType: FiscalDocumentType;
72
+ }): Promise<FiscalCoverage & {
73
+ jurisdictionKnown: boolean;
74
+ }>;
75
+ /** O catálogo inteiro, para a tela de cobertura. */
76
+ export declare function listFiscalCoverage(tx: Tx): Promise<FiscalCoverage[]>;
77
+ /**
78
+ * Existe alguma afirmação de cobertura NACIONAL para NFS-e municipal?
79
+ *
80
+ * A pergunta parece estranha e é o oráculo de `UNIVERSAL_NFSE_COVERAGE_ASSUMED`:
81
+ * o modelo passa se, e somente se, uma pergunta municipal sem medição não
82
+ * devolver "coberto". Um teste que só verificasse a linha nacional passaria com
83
+ * o defeito presente.
84
+ */
85
+ export declare function assumesUniversalNfseCoverage(tx: Tx): Promise<boolean>;
86
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/fiscal/coverage/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,MAAM,cAAc,GACtB,oBAAoB,GACpB,oBAAoB,GACpB,2BAA2B,GAC3B,SAAS,GACT,aAAa,CAAC;AAElB,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,kBAAkB,CAAC;IACjC,iBAAiB,EAAE,aAAa,CAAC;IACjC,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAC7B,YAAY,EAAE,kBAAkB,EAChC,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,cAAc,CAgBhB;AAsCD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE;IACL,YAAY,EAAE,kBAAkB,CAAC;IACjC,iBAAiB,EAAE,aAAa,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,GACA,OAAO,CAAC,cAAc,CAAC,CAwBzB;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,kBAAkB,CAAA;CAAE,GAC5D,OAAO,CAAC,cAAc,GAAG;IAAE,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAAC,CAoB1D;AAED,oDAAoD;AACpD,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAM1E;AAED;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ3E"}
@@ -0,0 +1,120 @@
1
+ import { loadClientJurisdiction } from '../repository.js';
2
+ /** A resposta quando nem a linha padrão existe. Desconhecida, nunca coberta. */
3
+ export function unknownCoverage(documentType, scope, code) {
4
+ return {
5
+ id: 'unknown',
6
+ documentType,
7
+ jurisdictionScope: scope,
8
+ jurisdictionCode: code,
9
+ provider: 'desconhecido',
10
+ coverageStatus: 'UNKNOWN',
11
+ automationMethod: null,
12
+ credentialRequirement: 'unknown',
13
+ environments: [],
14
+ fallbackType: 'manual_upload',
15
+ lastVerifiedAt: null,
16
+ sourceReference: null,
17
+ notes: 'Nenhuma linha de cobertura para esta combinação. Ninguém mediu.',
18
+ };
19
+ }
20
+ const map = (r) => ({
21
+ id: r.id,
22
+ documentType: r.document_type,
23
+ jurisdictionScope: r.jurisdiction_scope,
24
+ jurisdictionCode: r.jurisdiction_code,
25
+ provider: r.provider,
26
+ coverageStatus: r.coverage_status,
27
+ automationMethod: r.automation_method,
28
+ credentialRequirement: r.credential_requirement,
29
+ environments: r.environments ?? [],
30
+ fallbackType: r.fallback_type,
31
+ lastVerifiedAt: r.last_verified_at ? r.last_verified_at.toISOString().slice(0, 10) : null,
32
+ sourceReference: r.source_reference,
33
+ notes: r.notes,
34
+ });
35
+ const COLUMNS = `id, document_type, jurisdiction_scope, jurisdiction_code, provider,
36
+ coverage_status, automation_method, credential_requirement, environments,
37
+ fallback_type, last_verified_at, source_reference, notes`;
38
+ /**
39
+ * Resolve a cobertura de uma pergunta específica.
40
+ *
41
+ * Duas etapas, e a segunda NUNCA sobe de escopo: a linha exata do código, e
42
+ * depois a linha padrão do MESMO escopo. Não há terceira etapa.
43
+ */
44
+ export async function resolveFiscalCoverage(tx, input) {
45
+ const code = input.jurisdictionCode ?? null;
46
+ if (code) {
47
+ const exact = await tx `
48
+ SELECT ${tx.unsafe(COLUMNS)} FROM fiscal_coverage
49
+ WHERE document_type = ${input.documentType}
50
+ AND jurisdiction_scope = ${input.jurisdictionScope}
51
+ AND jurisdiction_code = ${code}
52
+ LIMIT 1
53
+ `;
54
+ if (exact[0])
55
+ return map(exact[0]);
56
+ }
57
+ const fallback = await tx `
58
+ SELECT ${tx.unsafe(COLUMNS)} FROM fiscal_coverage
59
+ WHERE document_type = ${input.documentType}
60
+ AND jurisdiction_scope = ${input.jurisdictionScope}
61
+ AND jurisdiction_code IS NULL
62
+ LIMIT 1
63
+ `;
64
+ if (fallback[0])
65
+ return { ...map(fallback[0]), jurisdictionCode: code };
66
+ return unknownCoverage(input.documentType, input.jurisdictionScope, code);
67
+ }
68
+ /**
69
+ * A cobertura que vale para um CLIENTE — a pergunta que a tela realmente faz.
70
+ *
71
+ * NFS-e é municipal por natureza: quem recolhe ISS é a prefeitura. Por isso a
72
+ * pergunta pelo cliente vai ao escopo municipal, e é ali que ela encontra
73
+ * `UNKNOWN` enquanto ninguém tiver medido a adesão daquele município. NF-e e
74
+ * CT-e são de distribuição nacional, e a pergunta é nacional.
75
+ */
76
+ export async function coverageForClient(tx, input) {
77
+ const jurisdiction = await loadClientJurisdiction(tx, input.clientId);
78
+ if (input.documentType === 'nfse') {
79
+ const coverage = await resolveFiscalCoverage(tx, {
80
+ documentType: 'nfse',
81
+ jurisdictionScope: 'municipal',
82
+ jurisdictionCode: jurisdiction.cityIbge,
83
+ });
84
+ // Sem o IBGE do cliente não dá para nem PERGUNTAR pelo município certo. É um
85
+ // dado que falta, e dizer isso é diferente de dizer que não há cobertura.
86
+ return { ...coverage, jurisdictionKnown: jurisdiction.cityIbge !== null };
87
+ }
88
+ const coverage = await resolveFiscalCoverage(tx, {
89
+ documentType: input.documentType,
90
+ jurisdictionScope: 'national',
91
+ jurisdictionCode: null,
92
+ });
93
+ return { ...coverage, jurisdictionKnown: true };
94
+ }
95
+ /** O catálogo inteiro, para a tela de cobertura. */
96
+ export async function listFiscalCoverage(tx) {
97
+ const rows = await tx `
98
+ SELECT ${tx.unsafe(COLUMNS)} FROM fiscal_coverage
99
+ ORDER BY document_type, jurisdiction_scope, jurisdiction_code NULLS FIRST
100
+ `;
101
+ return rows.map(map);
102
+ }
103
+ /**
104
+ * Existe alguma afirmação de cobertura NACIONAL para NFS-e municipal?
105
+ *
106
+ * A pergunta parece estranha e é o oráculo de `UNIVERSAL_NFSE_COVERAGE_ASSUMED`:
107
+ * o modelo passa se, e somente se, uma pergunta municipal sem medição não
108
+ * devolver "coberto". Um teste que só verificasse a linha nacional passaria com
109
+ * o defeito presente.
110
+ */
111
+ export async function assumesUniversalNfseCoverage(tx) {
112
+ const resolved = await resolveFiscalCoverage(tx, {
113
+ documentType: 'nfse',
114
+ jurisdictionScope: 'municipal',
115
+ // Um IBGE que ninguém mediu. É o caso da esmagadora maioria dos 5.570.
116
+ jurisdictionCode: '9999999',
117
+ });
118
+ return resolved.coverageStatus !== 'UNKNOWN';
119
+ }
120
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/fiscal/coverage/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { Tx } from '../../db/client.js';
2
+ import type { FiscalDocumentType } from '../ingestion/provider.js';
3
+ /**
4
+ * A ponte entre a coleta automática e a solicitação "Documentos fiscais do mês".
5
+ *
6
+ * ## A tentação, e por que ela está errada
7
+ *
8
+ * O caminho óbvio: chegou nota do cliente na competência ⇒ marque
9
+ * `docs_fiscais_mes` como concluída. Ele é errado por três motivos independentes,
10
+ * e qualquer um bastaria:
11
+ *
12
+ * 1. **Uma nota não é as notas.** O ADN traz o que o município publicou; a
13
+ * entrada de mercadoria do cliente pode nunca aparecer ali. Fechar a
14
+ * solicitação com uma nota de saída faz o escritório parar de perguntar
15
+ * pelas de entrada.
16
+ * 2. **A cobertura pode ser desconhecida.** Se a prefeitura não aderiu ao ADN,
17
+ * a automação nunca trará nada — e fechar por ausência seria pior ainda.
18
+ * 3. **Concluir é ato de quem confere.** A solicitação existe porque alguém
19
+ * precisa OLHAR o conjunto. Um robô que a fecha remove a conferência sem
20
+ * substituí-la.
21
+ *
22
+ * Por isso este módulo **não escreve nada**. Ele CLASSIFICA, e a classificação
23
+ * aparece ao lado da solicitação para que a pessoa decida com mais informação —
24
+ * que é o oposto de decidir por ela.
25
+ */
26
+ export type RequestCoverageLevel = 'NOT_COVERED' | 'PARTIALLY_COVERED' | 'FULLY_COVERED_BY_AUTOMATION';
27
+ export interface RequestCoverageAssessment {
28
+ clientId: string;
29
+ competenceLabel: string;
30
+ level: RequestCoverageLevel;
31
+ /** Documentos coletados automaticamente naquela competência. */
32
+ automaticDocuments: number;
33
+ /** Direções presentes. Só saída é sinal de cobertura parcial, não total. */
34
+ directions: readonly string[];
35
+ coverageStatus: string;
36
+ /** Nunca é verdadeiro nesta fase. O campo existe para tornar isso auditável. */
37
+ autoClosed: false;
38
+ detail: string;
39
+ }
40
+ /**
41
+ * Classifica a cobertura da solicitação de uma competência.
42
+ *
43
+ * `FULLY_COVERED_BY_AUTOMATION` exige as DUAS condições, e não uma:
44
+ * cobertura oficial declarada para a jurisdição E documentos de entrada e saída
45
+ * presentes. Com só uma delas, o máximo é `PARTIALLY_COVERED` — porque só uma
46
+ * delas é, literalmente, cobertura parcial.
47
+ */
48
+ export declare function assessRequestCoverage(tx: Tx, input: {
49
+ clientId: string;
50
+ competenceLabel: string;
51
+ documentType?: FiscalDocumentType;
52
+ }): Promise<RequestCoverageAssessment>;
53
+ export interface RequestCoverageRow extends RequestCoverageAssessment {
54
+ requestId: string;
55
+ clientName: string | null;
56
+ status: string;
57
+ dueDate: string | null;
58
+ }
59
+ /**
60
+ * As solicitações de "Documentos fiscais do mês" com sua classificação.
61
+ *
62
+ * Leitura pura. Nenhuma linha de `recurring_instance` é tocada — e um teste
63
+ * confere isso comparando o `updated_at` das solicitações antes e depois, porque
64
+ * "eu não escrevi nada" é uma afirmação que precisa de oráculo.
65
+ */
66
+ export declare function listRequestCoverage(tx: Tx, input?: {
67
+ competenceLabel?: string;
68
+ limit?: number;
69
+ }): Promise<RequestCoverageRow[]>;
70
+ //# sourceMappingURL=requests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.d.ts","sourceRoot":"","sources":["../../../src/fiscal/coverage/requests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,MAAM,oBAAoB,GAC5B,aAAa,GACb,mBAAmB,GACnB,6BAA6B,CAAC;AAElC,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,oBAAoB,CAAC;IAC5B,gEAAgE;IAChE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,UAAU,EAAE,KAAK,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC,GACA,OAAO,CAAC,yBAAyB,CAAC,CAuDpC;AAED,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,EAAE,EACN,KAAK,GAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACvD,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAwC/B"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Classifica a cobertura da solicitação de uma competência.
3
+ *
4
+ * `FULLY_COVERED_BY_AUTOMATION` exige as DUAS condições, e não uma:
5
+ * cobertura oficial declarada para a jurisdição E documentos de entrada e saída
6
+ * presentes. Com só uma delas, o máximo é `PARTIALLY_COVERED` — porque só uma
7
+ * delas é, literalmente, cobertura parcial.
8
+ */
9
+ export async function assessRequestCoverage(tx, input) {
10
+ const documentType = input.documentType ?? 'nfse';
11
+ const [doc] = await tx `
12
+ SELECT count(*)::int AS total,
13
+ coalesce(array_agg(DISTINCT direction), '{}') AS direcoes
14
+ FROM fiscal_document
15
+ WHERE client_id = ${input.clientId}
16
+ AND competence_label = ${input.competenceLabel}
17
+ AND source <> 'manual'
18
+ `;
19
+ const [cov] = await tx `
20
+ SELECT fc.coverage_status
21
+ FROM client c
22
+ LEFT JOIN fiscal_coverage fc
23
+ ON fc.document_type = ${documentType}
24
+ AND fc.jurisdiction_scope = ${documentType === 'nfse' ? 'municipal' : 'national'}
25
+ AND (fc.jurisdiction_code = c.municipality_ibge_code OR fc.jurisdiction_code IS NULL)
26
+ WHERE c.id = ${input.clientId}
27
+ ORDER BY fc.jurisdiction_code NULLS LAST
28
+ LIMIT 1
29
+ `;
30
+ const coverageStatus = cov?.coverage_status ?? 'UNKNOWN';
31
+ const total = doc?.total ?? 0;
32
+ const direcoes = doc?.direcoes ?? [];
33
+ const oficial = coverageStatus === 'SUPPORTED_OFFICIAL' || coverageStatus === 'SUPPORTED_PROVIDER';
34
+ const temEntradaESaida = direcoes.includes('received') && direcoes.includes('issued');
35
+ const level = total === 0
36
+ ? 'NOT_COVERED'
37
+ : oficial && temEntradaESaida
38
+ ? 'FULLY_COVERED_BY_AUTOMATION'
39
+ : 'PARTIALLY_COVERED';
40
+ return {
41
+ clientId: input.clientId,
42
+ competenceLabel: input.competenceLabel,
43
+ level,
44
+ automaticDocuments: total,
45
+ directions: direcoes,
46
+ coverageStatus,
47
+ autoClosed: false,
48
+ detail: level === 'NOT_COVERED'
49
+ ? 'Nenhum documento coletado automaticamente nesta competência.'
50
+ : level === 'FULLY_COVERED_BY_AUTOMATION'
51
+ ? `${total} documentos coletados, com entrada e saída, em jurisdição com cobertura oficial.`
52
+ : oficial
53
+ ? `${total} documentos coletados, mas falta ${direcoes.includes('issued') ? 'documento de entrada' : 'documento de saída'}.`
54
+ : `${total} documentos coletados, porém a cobertura desta jurisdição é ${coverageStatus}.`,
55
+ };
56
+ }
57
+ /**
58
+ * As solicitações de "Documentos fiscais do mês" com sua classificação.
59
+ *
60
+ * Leitura pura. Nenhuma linha de `recurring_instance` é tocada — e um teste
61
+ * confere isso comparando o `updated_at` das solicitações antes e depois, porque
62
+ * "eu não escrevi nada" é uma afirmação que precisa de oráculo.
63
+ */
64
+ export async function listRequestCoverage(tx, input = {}) {
65
+ const limit = Math.min(Math.max(input.limit ?? 100, 1), 500);
66
+ const rows = await tx `
67
+ SELECT ri.id AS request_id, ri.client_id, c.display_name AS client_name,
68
+ ri.status, ri.due_date, comp.label AS competence_label
69
+ FROM recurring_instance ri
70
+ JOIN recurring_item_type rit ON rit.id = ri.item_type_id
71
+ JOIN competence comp ON comp.id = ri.competence_id
72
+ JOIN client c ON c.id = ri.client_id
73
+ WHERE rit.key = 'docs_fiscais_mes'
74
+ AND ri.deleted_at IS NULL
75
+ AND ${input.competenceLabel ? tx `comp.label = ${input.competenceLabel}` : tx `true`}
76
+ ORDER BY comp.label DESC, c.display_name
77
+ LIMIT ${limit}
78
+ `;
79
+ const out = [];
80
+ for (const r of rows) {
81
+ const assessment = await assessRequestCoverage(tx, {
82
+ clientId: r.client_id,
83
+ competenceLabel: r.competence_label,
84
+ });
85
+ out.push({
86
+ ...assessment,
87
+ requestId: r.request_id,
88
+ clientName: r.client_name,
89
+ status: r.status,
90
+ dueDate: r.due_date ? r.due_date.toISOString().slice(0, 10) : null,
91
+ });
92
+ }
93
+ return out;
94
+ }
95
+ //# sourceMappingURL=requests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.js","sourceRoot":"","sources":["../../../src/fiscal/coverage/requests.ts"],"names":[],"mappings":"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"}