ekwo-os 0.4.1

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 (361) hide show
  1. package/README.md +873 -0
  2. package/dist/args.d.ts +57 -0
  3. package/dist/args.d.ts.map +1 -0
  4. package/dist/args.js +134 -0
  5. package/dist/args.js.map +1 -0
  6. package/dist/assets/expected-objects.json +9432 -0
  7. package/dist/assets/migrations/20260911120000_core_companies.sql +260 -0
  8. package/dist/assets/migrations/20260911120100_accounts_journals.sql +211 -0
  9. package/dist/assets/migrations/20260911120200_contacts.sql +90 -0
  10. package/dist/assets/migrations/20260911120300_taxes.sql +146 -0
  11. package/dist/assets/migrations/20260911120400_entries.sql +338 -0
  12. package/dist/assets/migrations/20260911120500_documents.sql +279 -0
  13. package/dist/assets/migrations/20260911120600_payments_reconciliation.sql +251 -0
  14. package/dist/assets/migrations/20260911120700_bank.sql +178 -0
  15. package/dist/assets/migrations/20260911120800_analytics_attachments.sql +128 -0
  16. package/dist/assets/migrations/20260911120900_post_document.sql +279 -0
  17. package/dist/assets/migrations/20260911121000_reporting.sql +235 -0
  18. package/dist/assets/migrations/20260911121100_country_templates.sql +226 -0
  19. package/dist/assets/migrations/20260911121200_fec.sql +71 -0
  20. package/dist/assets/migrations/20260911130000_instance.sql +77 -0
  21. package/dist/assets/migrations/20260911130100_instance_members.sql +224 -0
  22. package/dist/assets/migrations/20260911140000_instance_admins.sql +112 -0
  23. package/dist/assets/migrations/20260911160000_tax_posting_templates_unique.sql +17 -0
  24. package/dist/assets/migrations/20260911170000_document_amount_paid.sql +82 -0
  25. package/dist/assets/migrations/20260911173000_post_payment.sql +122 -0
  26. package/dist/assets/migrations/20260911173100_sequence_counters_under_rls.sql +84 -0
  27. package/dist/assets/migrations/20260911183000_country_journal_defaults.sql +143 -0
  28. package/dist/assets/migrations/20260911193853_line_account_defaults.sql +274 -0
  29. package/dist/assets/migrations/20260911195054_products.sql +221 -0
  30. package/dist/assets/migrations/20260911210131_anon_surface.sql +85 -0
  31. package/dist/assets/migrations/20260912074712_country_packs.sql +318 -0
  32. package/dist/assets/migrations/20260912080311_report_code_and_region.sql +198 -0
  33. package/dist/assets/migrations/20260912081014_pack_certification_maintained.sql +31 -0
  34. package/dist/assets/migrations/20260912081015_pack_certification_backfill.sql +16 -0
  35. package/dist/assets/migrations/20260912090407_tax_report_boxes.sql +329 -0
  36. package/dist/assets/migrations/20260912091917_tax_on_base_value.sql +25 -0
  37. package/dist/assets/migrations/20260912091918_tax_engine_columns.sql +776 -0
  38. package/dist/assets/migrations/20260912094412_opening_and_closing.sql +759 -0
  39. package/dist/assets/migrations/20260912095825_charts_of_accounts.sql +326 -0
  40. package/dist/assets/migrations/20260912100412_financial_statements.sql +632 -0
  41. package/dist/assets/migrations/20260912104719_one_formula_evaluator.sql +209 -0
  42. package/dist/assets/migrations/20260912105720_entry_kind_appropriation.sql +26 -0
  43. package/dist/assets/migrations/20260912105721_appropriation_entry_kind.sql +444 -0
  44. package/dist/assets/migrations/20260912111751_document_rules.sql +274 -0
  45. package/dist/assets/migrations/20260912112132_cash_basis_vat_and_fx.sql +1189 -0
  46. package/dist/assets/migrations/20260913074512_modules.sql +493 -0
  47. package/dist/assets/migrations/20260913075903_asset_disposal_roles.sql +47 -0
  48. package/dist/assets/migrations/20260913083216_capabilities.sql +637 -0
  49. package/dist/assets/migrations/20260913083901_company_invitations.sql +262 -0
  50. package/dist/assets/migrations/20260913084402_user_preferences.sql +376 -0
  51. package/dist/assets/migrations/20260913084847_company_profile.sql +261 -0
  52. package/dist/assets/migrations/20260913085436_numbering_reads_the_pack.sql +235 -0
  53. package/dist/assets/migrations/20260913085932_api_keys.sql +303 -0
  54. package/dist/assets/migrations/20260913090216_fiscal_year_bounds.sql +159 -0
  55. package/dist/assets/migrations/20260913092527_entries_import.sql +219 -0
  56. package/dist/assets/migrations/20260913101536_null_safe_guards.sql +188 -0
  57. package/dist/assets/migrations/20260913102115_installer_is_named.sql +462 -0
  58. package/dist/assets/migrations/20260913102758_no_currency_default.sql +138 -0
  59. package/dist/assets/migrations/20260913103355_cash_basis_needs_a_box.sql +453 -0
  60. package/dist/assets/migrations/20260913104014_aged_balance_named_group.sql +79 -0
  61. package/dist/assets/migrations/20260913104232_foreign_key_indexes.sql +144 -0
  62. package/dist/assets/migrations/20260913105120_declared_no_reader.sql +41 -0
  63. package/dist/assets/migrations/20260913111407_pack_languages.sql +223 -0
  64. package/dist/assets/migrations/20260913112233_schema_comments_for_a_reader.sql +27 -0
  65. package/dist/assets/migrations/20260913114535_fec_opening_balances.sql +307 -0
  66. package/dist/assets/migrations/20260914103412_audit_log.sql +509 -0
  67. package/dist/assets/migrations/20260914111907_pack_upgrade.sql +428 -0
  68. package/dist/assets/migrations/20260914120500_rounding_reads_the_currency.sql +206 -0
  69. package/dist/assets/migrations/20260914121200_amounts_round_at_the_currency.sql +2403 -0
  70. package/dist/assets/migrations/20260914134325_schema_version_0_2_0.sql +36 -0
  71. package/dist/assets/migrations/20260914143915_accounts_in_use.sql +428 -0
  72. package/dist/assets/migrations/20260914144731_account_code_frozen.sql +99 -0
  73. package/dist/assets/migrations/20260914151207_schema_grants_its_own_rights.sql +284 -0
  74. package/dist/assets/migrations/20260914152840_pack_upgrade_records_its_own_line.sql +237 -0
  75. package/dist/assets/migrations/20260914163943_declaration_periodicity.sql +349 -0
  76. package/dist/assets/migrations/20260915094000_foreign_services_received.sql +37 -0
  77. package/dist/assets/migrations/20260915094500_mentions_read_a_foreign_service.sql +72 -0
  78. package/dist/assets/migrations/20260915153000_document_shares.sql +568 -0
  79. package/dist/assets/migrations/20260915160000_ec_sales_list.sql +181 -0
  80. package/dist/assets/migrations/20260915161842_pack_sources.sql +56 -0
  81. package/dist/assets/migrations/20260915170500_schema_version_0_3_0.sql +45 -0
  82. package/dist/assets/migrations/20260915174500_a_vat_category_is_a_code.sql +177 -0
  83. package/dist/assets/migrations/20260915180000_document_rule_references.sql +85 -0
  84. package/dist/assets/migrations/20260915181000_territories.sql +342 -0
  85. package/dist/assets/migrations/20260915181500_ec_sales_list_reads_the_territories.sql +222 -0
  86. package/dist/assets/migrations/20260915182000_intracom_triangular.sql +53 -0
  87. package/dist/assets/migrations/20260915182500_a_triangular_supply_says_reverse_charge.sql +99 -0
  88. package/dist/assets/migrations/20260915191200_a_document_knows_its_language.sql +633 -0
  89. package/dist/assets/migrations/20260915195000_a_price_that_holds_its_tax.sql +649 -0
  90. package/dist/assets/migrations/20260915200000_a_posting_names_its_boxes.sql +1004 -0
  91. package/dist/assets/migrations/20260916094500_a_company_files_more_than_one_declaration.sql +795 -0
  92. package/dist/assets/migrations/20260916103000_a_ledger_line_names_its_posting.sql +902 -0
  93. package/dist/assets/migrations/20260916123000_a_vocabulary_for_a_tax_that_is_not_a_vat.sql +144 -0
  94. package/dist/assets/migrations/20260916124000_a_box_can_be_a_rate_of_a_box.sql +525 -0
  95. package/dist/assets/migrations/20260916125000_a_tax_follows_the_territory.sql +1318 -0
  96. package/dist/assets/migrations/20260916126000_a_tax_point_and_its_exception.sql +1211 -0
  97. package/dist/assets/migrations/20260917090000_a_counterparty_that_learns.sql +561 -0
  98. package/dist/assets/migrations/20260917120000_what_the_money_pays.sql +545 -0
  99. package/dist/assets/migrations/20260917150000_a_filing_is_a_row.sql +488 -0
  100. package/dist/assets/migrations/20260917170000_when_it_is_due.sql +194 -0
  101. package/dist/assets/migrations/20260917180000_a_box_is_a_number_and_a_kind.sql +213 -0
  102. package/dist/assets/migrations/20260917190000_what_a_declaration_owes.sql +486 -0
  103. package/dist/assets/migrations/20260917200000_what_moved_after_it_went.sql +227 -0
  104. package/dist/assets/migrations/20260918090000_a_form_names_its_file.sql +27 -0
  105. package/dist/assets/migrations/20260918110000_a_deposit_and_what_came_back.sql +286 -0
  106. package/dist/assets/migrations/20260918113741_a_fourth_preset_is_named.sql +9 -0
  107. package/dist/assets/migrations/20260918113807_a_client_reads_and_hands_over.sql +96 -0
  108. package/dist/assets/migrations/20260918114322_two_definer_functions_check_their_caller.sql +75 -0
  109. package/dist/assets/migrations/20260918130000_every_company_somebody_keeps.sql +177 -0
  110. package/dist/assets/migrations/20260918140000_a_session_nobody_prepared.sql +40 -0
  111. package/dist/assets/migrations/20260918141107_a_line_keeps_the_tax_it_was_posted_with.sql +256 -0
  112. package/dist/assets/migrations/20260918141342_a_company_has_an_electronic_address.sql +66 -0
  113. package/dist/assets/migrations/20260918141605_an_invoice_reads_whole_from_the_views.sql +313 -0
  114. package/dist/assets/migrations/20260918141627_a_policy_asks_once.sql +132 -0
  115. package/dist/assets/migrations/20260918143352_a_suggestion_reads_the_words_once.sql +204 -0
  116. package/dist/assets/migrations/20260918143417_a_reference_of_the_caller_and_a_rehearsal.sql +115 -0
  117. package/dist/assets/migrations/20260918150712_a_company_leaves_with_its_books.sql +1119 -0
  118. package/dist/assets/migrations/20260918150931_a_statement_is_imported_once.sql +654 -0
  119. package/dist/assets/migrations/20260918161204_a_posted_document_does_not_move.sql +437 -0
  120. package/dist/assets/migrations/20260918161538_a_posted_entry_does_not_move.sql +252 -0
  121. package/dist/assets/migrations/20260918171946_an_entry_is_posted_by_post_entry.sql +289 -0
  122. package/dist/assets/migrations/20260918174312_schema_version_0_4_0.sql +53 -0
  123. package/dist/assets/modules/assets/module.json +13 -0
  124. package/dist/assets/modules/assets/supabase/migrations/20260913081447_assets.sql +1190 -0
  125. package/dist/assets/modules/assets/supabase/migrations/20260913104234_foreign_key_indexes.sql +47 -0
  126. package/dist/assets/modules/assets/supabase/migrations/20260913104500_assets_capabilities.sql +145 -0
  127. package/dist/assets/modules/assets/supabase/migrations/20260914122100_assets_round_at_the_currency.sql +564 -0
  128. package/dist/assets/modules/assets/supabase/migrations/20260914145012_assets_accounts_in_use.sql +37 -0
  129. package/dist/assets/modules/assets/supabase/migrations/20260914151530_assets_grants_its_own_rights.sql +63 -0
  130. package/dist/assets/modules/assets/supabase/migrations/20260918113912_assets_client_reads.sql +20 -0
  131. package/dist/assets/modules/assets/supabase/migrations/20260918150801_assets_leave_with_the_company.sql +41 -0
  132. package/dist/assets/modules/budgets/module.json +12 -0
  133. package/dist/assets/modules/budgets/supabase/migrations/20260913083012_budgets.sql +210 -0
  134. package/dist/assets/modules/budgets/supabase/migrations/20260913104233_foreign_key_indexes.sql +37 -0
  135. package/dist/assets/modules/budgets/supabase/migrations/20260913104501_budgets_capabilities.sql +72 -0
  136. package/dist/assets/modules/budgets/supabase/migrations/20260914122400_budgets_round_at_the_currency.sql +68 -0
  137. package/dist/assets/modules/budgets/supabase/migrations/20260914145048_budgets_accounts_in_use.sql +30 -0
  138. package/dist/assets/modules/budgets/supabase/migrations/20260914151812_budgets_grants_its_own_rights.sql +31 -0
  139. package/dist/assets/modules/budgets/supabase/migrations/20260918113954_budgets_client_reads.sql +20 -0
  140. package/dist/assets/modules/budgets/supabase/migrations/20260918150823_budgets_leave_with_the_company.sql +37 -0
  141. package/dist/assets/modules/schema/module.1.json +69 -0
  142. package/dist/assets/seed/00_currencies.sql +15 -0
  143. package/dist/assets/seed/00_territories.sql +280 -0
  144. package/dist/assets/seed/05_framework_generic.sql +110 -0
  145. package/dist/assets/seed/10_pack_be.sql +1284 -0
  146. package/dist/assets/seed/11_pack_fr.sql +1112 -0
  147. package/dist/assets/seed/12_pack_lu.sql +2484 -0
  148. package/dist/assets/seed/13_pack_ee.sql +733 -0
  149. package/dist/assets/seed/14_pack_gb.sql +796 -0
  150. package/dist/assets/seed/15_pack_us.sql +751 -0
  151. package/dist/assets/seed/90_demo_company.sql +368 -0
  152. package/dist/assets/seed/modules/assets/10_pack_be.sql +58 -0
  153. package/dist/assets/seed/modules/assets/11_pack_fr.sql +57 -0
  154. package/dist/assets/seed/modules/assets/14_pack_gb.sql +58 -0
  155. package/dist/assets/seed/modules/assets/15_pack_us.sql +60 -0
  156. package/dist/auth.d.ts +59 -0
  157. package/dist/auth.d.ts.map +1 -0
  158. package/dist/auth.js +134 -0
  159. package/dist/auth.js.map +1 -0
  160. package/dist/bin.d.ts +6 -0
  161. package/dist/bin.d.ts.map +1 -0
  162. package/dist/bin.js +8 -0
  163. package/dist/bin.js.map +1 -0
  164. package/dist/books.d.ts +60 -0
  165. package/dist/books.d.ts.map +1 -0
  166. package/dist/books.js +168 -0
  167. package/dist/books.js.map +1 -0
  168. package/dist/bootstrap.d.ts +236 -0
  169. package/dist/bootstrap.d.ts.map +1 -0
  170. package/dist/bootstrap.js +459 -0
  171. package/dist/bootstrap.js.map +1 -0
  172. package/dist/bundle.d.ts +27 -0
  173. package/dist/bundle.d.ts.map +1 -0
  174. package/dist/bundle.js +47 -0
  175. package/dist/bundle.js.map +1 -0
  176. package/dist/checklist.d.ts +35 -0
  177. package/dist/checklist.d.ts.map +1 -0
  178. package/dist/checklist.js +64 -0
  179. package/dist/checklist.js.map +1 -0
  180. package/dist/cli.d.ts +14 -0
  181. package/dist/cli.d.ts.map +1 -0
  182. package/dist/cli.js +318 -0
  183. package/dist/cli.js.map +1 -0
  184. package/dist/commands/company.d.ts +59 -0
  185. package/dist/commands/company.d.ts.map +1 -0
  186. package/dist/commands/company.js +287 -0
  187. package/dist/commands/company.js.map +1 -0
  188. package/dist/commands/contact.d.ts +9 -0
  189. package/dist/commands/contact.d.ts.map +1 -0
  190. package/dist/commands/contact.js +82 -0
  191. package/dist/commands/contact.js.map +1 -0
  192. package/dist/commands/demo.d.ts +19 -0
  193. package/dist/commands/demo.d.ts.map +1 -0
  194. package/dist/commands/demo.js +72 -0
  195. package/dist/commands/demo.js.map +1 -0
  196. package/dist/commands/doctor.d.ts +12 -0
  197. package/dist/commands/doctor.d.ts.map +1 -0
  198. package/dist/commands/doctor.js +68 -0
  199. package/dist/commands/doctor.js.map +1 -0
  200. package/dist/commands/document.d.ts +17 -0
  201. package/dist/commands/document.d.ts.map +1 -0
  202. package/dist/commands/document.js +217 -0
  203. package/dist/commands/document.js.map +1 -0
  204. package/dist/commands/init.d.ts +31 -0
  205. package/dist/commands/init.d.ts.map +1 -0
  206. package/dist/commands/init.js +535 -0
  207. package/dist/commands/init.js.map +1 -0
  208. package/dist/commands/login.d.ts +24 -0
  209. package/dist/commands/login.d.ts.map +1 -0
  210. package/dist/commands/login.js +128 -0
  211. package/dist/commands/login.js.map +1 -0
  212. package/dist/commands/migrate.d.ts +30 -0
  213. package/dist/commands/migrate.d.ts.map +1 -0
  214. package/dist/commands/migrate.js +115 -0
  215. package/dist/commands/migrate.js.map +1 -0
  216. package/dist/commands/module.d.ts +32 -0
  217. package/dist/commands/module.d.ts.map +1 -0
  218. package/dist/commands/module.js +285 -0
  219. package/dist/commands/module.js.map +1 -0
  220. package/dist/commands/pack.d.ts +22 -0
  221. package/dist/commands/pack.d.ts.map +1 -0
  222. package/dist/commands/pack.js +481 -0
  223. package/dist/commands/pack.js.map +1 -0
  224. package/dist/commands/payment.d.ts +15 -0
  225. package/dist/commands/payment.d.ts.map +1 -0
  226. package/dist/commands/payment.js +97 -0
  227. package/dist/commands/payment.js.map +1 -0
  228. package/dist/commands/register.d.ts +20 -0
  229. package/dist/commands/register.d.ts.map +1 -0
  230. package/dist/commands/register.js +134 -0
  231. package/dist/commands/register.js.map +1 -0
  232. package/dist/commands/status.d.ts +8 -0
  233. package/dist/commands/status.d.ts.map +1 -0
  234. package/dist/commands/status.js +134 -0
  235. package/dist/commands/status.js.map +1 -0
  236. package/dist/commands/whoami.d.ts +21 -0
  237. package/dist/commands/whoami.d.ts.map +1 -0
  238. package/dist/commands/whoami.js +133 -0
  239. package/dist/commands/whoami.js.map +1 -0
  240. package/dist/company.d.ts +16 -0
  241. package/dist/company.d.ts.map +1 -0
  242. package/dist/company.js +26 -0
  243. package/dist/company.js.map +1 -0
  244. package/dist/config.d.ts +24 -0
  245. package/dist/config.d.ts.map +1 -0
  246. package/dist/config.js +50 -0
  247. package/dist/config.js.map +1 -0
  248. package/dist/connection.d.ts +79 -0
  249. package/dist/connection.d.ts.map +1 -0
  250. package/dist/connection.js +116 -0
  251. package/dist/connection.js.map +1 -0
  252. package/dist/context.d.ts +47 -0
  253. package/dist/context.d.ts.map +1 -0
  254. package/dist/context.js +93 -0
  255. package/dist/context.js.map +1 -0
  256. package/dist/doctor.d.ts +45 -0
  257. package/dist/doctor.d.ts.map +1 -0
  258. package/dist/doctor.js +448 -0
  259. package/dist/doctor.js.map +1 -0
  260. package/dist/grants.d.ts +88 -0
  261. package/dist/grants.d.ts.map +1 -0
  262. package/dist/grants.js +174 -0
  263. package/dist/grants.js.map +1 -0
  264. package/dist/identity.d.ts +54 -0
  265. package/dist/identity.d.ts.map +1 -0
  266. package/dist/identity.js +132 -0
  267. package/dist/identity.js.map +1 -0
  268. package/dist/index.d.ts +44 -0
  269. package/dist/index.d.ts.map +1 -0
  270. package/dist/index.js +43 -0
  271. package/dist/index.js.map +1 -0
  272. package/dist/inventory.d.ts +155 -0
  273. package/dist/inventory.d.ts.map +1 -0
  274. package/dist/inventory.js +303 -0
  275. package/dist/inventory.js.map +1 -0
  276. package/dist/migrations.d.ts +76 -0
  277. package/dist/migrations.d.ts.map +1 -0
  278. package/dist/migrations.js +226 -0
  279. package/dist/migrations.js.map +1 -0
  280. package/dist/module/read.d.ts +91 -0
  281. package/dist/module/read.d.ts.map +1 -0
  282. package/dist/module/read.js +172 -0
  283. package/dist/module/read.js.map +1 -0
  284. package/dist/output.d.ts +110 -0
  285. package/dist/output.d.ts.map +1 -0
  286. package/dist/output.js +173 -0
  287. package/dist/output.js.map +1 -0
  288. package/dist/pack/certification.d.ts +27 -0
  289. package/dist/pack/certification.d.ts.map +1 -0
  290. package/dist/pack/certification.js +38 -0
  291. package/dist/pack/certification.js.map +1 -0
  292. package/dist/pack/compile.d.ts +75 -0
  293. package/dist/pack/compile.d.ts.map +1 -0
  294. package/dist/pack/compile.js +801 -0
  295. package/dist/pack/compile.js.map +1 -0
  296. package/dist/pack/filing.d.ts +48 -0
  297. package/dist/pack/filing.d.ts.map +1 -0
  298. package/dist/pack/filing.js +56 -0
  299. package/dist/pack/filing.js.map +1 -0
  300. package/dist/pack/read.d.ts +766 -0
  301. package/dist/pack/read.d.ts.map +1 -0
  302. package/dist/pack/read.js +2336 -0
  303. package/dist/pack/read.js.map +1 -0
  304. package/dist/pack/schema.d.ts +26 -0
  305. package/dist/pack/schema.d.ts.map +1 -0
  306. package/dist/pack/schema.js +181 -0
  307. package/dist/pack/schema.js.map +1 -0
  308. package/dist/pack/territories.d.ts +98 -0
  309. package/dist/pack/territories.d.ts.map +1 -0
  310. package/dist/pack/territories.js +0 -0
  311. package/dist/pack/territories.js.map +1 -0
  312. package/dist/pack/upgrade.d.ts +86 -0
  313. package/dist/pack/upgrade.d.ts.map +1 -0
  314. package/dist/pack/upgrade.js +76 -0
  315. package/dist/pack/upgrade.js.map +1 -0
  316. package/dist/pack/vat-codes.d.ts +273 -0
  317. package/dist/pack/vat-codes.d.ts.map +1 -0
  318. package/dist/pack/vat-codes.js +513 -0
  319. package/dist/pack/vat-codes.js.map +1 -0
  320. package/dist/profiles.d.ts +67 -0
  321. package/dist/profiles.d.ts.map +1 -0
  322. package/dist/profiles.js +187 -0
  323. package/dist/profiles.js.map +1 -0
  324. package/dist/prompt.d.ts +40 -0
  325. package/dist/prompt.d.ts.map +1 -0
  326. package/dist/prompt.js +120 -0
  327. package/dist/prompt.js.map +1 -0
  328. package/dist/registry.d.ts +84 -0
  329. package/dist/registry.d.ts.map +1 -0
  330. package/dist/registry.js +104 -0
  331. package/dist/registry.js.map +1 -0
  332. package/dist/rest.d.ts +81 -0
  333. package/dist/rest.d.ts.map +1 -0
  334. package/dist/rest.js +245 -0
  335. package/dist/rest.js.map +1 -0
  336. package/dist/schema.d.ts +15 -0
  337. package/dist/schema.d.ts.map +1 -0
  338. package/dist/schema.js +15 -0
  339. package/dist/schema.js.map +1 -0
  340. package/dist/seeds.d.ts +27 -0
  341. package/dist/seeds.d.ts.map +1 -0
  342. package/dist/seeds.js +47 -0
  343. package/dist/seeds.js.map +1 -0
  344. package/dist/session.d.ts +39 -0
  345. package/dist/session.d.ts.map +1 -0
  346. package/dist/session.js +92 -0
  347. package/dist/session.js.map +1 -0
  348. package/dist/sql.d.ts +48 -0
  349. package/dist/sql.d.ts.map +1 -0
  350. package/dist/sql.js +112 -0
  351. package/dist/sql.js.map +1 -0
  352. package/dist/status.d.ts +94 -0
  353. package/dist/status.d.ts.map +1 -0
  354. package/dist/status.js +120 -0
  355. package/dist/status.js.map +1 -0
  356. package/dist/ui.d.ts +55 -0
  357. package/dist/ui.d.ts.map +1 -0
  358. package/dist/ui.js +114 -0
  359. package/dist/ui.js.map +1 -0
  360. package/package.json +29 -0
  361. package/schema/output.1.json +613 -0
@@ -0,0 +1,437 @@
1
+ -- Ekwo OS — what produced an entry stops moving when the entry exists.
2
+ --
3
+ -- A document is posted once: `post_document()` reads its lines, builds the
4
+ -- entry, and refuses to do it twice. From then on the ledger holds the figures
5
+ -- of that day — and the document did not. Nothing guarded it. Established
6
+ -- under row level security, as a member holding `documents.write` and nothing
7
+ -- more, on a posted invoice in an open period:
8
+ --
9
+ -- * every column of `document_lines` could be rewritten — quantity, price,
10
+ -- discount, tax, account, name — a line could be added and a line could be
11
+ -- deleted, and the totals of the document followed: an invoice posted at
12
+ -- 150 read 750, 1 149 or 50 a statement later, against a ledger still at
13
+ -- 150;
14
+ -- * every column of `documents` too: the three totals, the number, the three
15
+ -- dates, the customer, the currency and its rate, the type, the journal;
16
+ -- `entry_id` could be nulled, which unhooks the document from its entry;
17
+ -- `state` could go back to `draft`, after which `post_document()` books it
18
+ -- a second time; it could be set to `cancelled`, which reverses nothing;
19
+ -- and the row could be deleted, leaving its entry with no document;
20
+ -- * what was refused: the language (`document_language_frozen`), the
21
+ -- category and the rate of a line (`document_line_tax_frozen`, a day old),
22
+ -- and a second `post_document()`. The period locks guard `entries` and
23
+ -- `entry_lines` and say nothing of a document.
24
+ --
25
+ -- So an issued invoice was immutable by convention. This file makes it so by
26
+ -- the database, in the shape `tax_filing_boxes_are_frozen` has: a trigger that
27
+ -- asks one question — has the state left `draft`? — and refuses by name.
28
+ --
29
+ -- **The rule is a closed list of what may still move, not a list of what may
30
+ -- not.** A column added next month is frozen the day it is added, without
31
+ -- anybody remembering this file. What may move on a document that is no longer
32
+ -- a draft:
33
+ --
34
+ -- * `amount_paid`, and only to the figure the matching gives — so the guard
35
+ -- judges the value and not the path: `reconcile()`, `unreconcile()` and
36
+ -- whatever settles a document tomorrow all pass, and a figure keyed by
37
+ -- hand does not. `document_amount_paid()` is that figure, taken out of
38
+ -- `documents_refresh_amount_paid()` so that the two cannot disagree.
39
+ -- `payment_state` and `amount_residual` follow from it and are never
40
+ -- written: the first by trigger, the second by the column's own
41
+ -- definition;
42
+ -- * `sent_at`, `peppol_status`, `peppol_message_id`: what happened to the
43
+ -- document *after* it was issued, which by definition is written after;
44
+ -- * `updated_at`.
45
+ --
46
+ -- Nothing else, and in particular not `due_date` (it is BT-9 on the invoice
47
+ -- and the maturity of the receivable in the ledger), not `note` (BT-22 is
48
+ -- printed; there is no internal note on this table, and the day there is one
49
+ -- it joins the list by name), not `reversed_document_id` (a credit note names
50
+ -- what it credits while it is a draft). Attachments and share links are rows
51
+ -- of other tables and are not touched: filing a scan under an invoice, or
52
+ -- sending its link, changes nothing the customer was issued.
53
+ --
54
+ -- **The state goes one way.** `draft` to `posted` is the transition
55
+ -- `post_document()` makes, in one statement, and it passes untouched because
56
+ -- the row it updates is still a draft; the guard adds only that a document
57
+ -- does not become posted without an entry that is itself posted. `draft` to `cancelled` is a draft
58
+ -- abandoned. Out of `posted` there is no way: not back to `draft`, and not to
59
+ -- `cancelled` either — no function of this schema cancels a posted document,
60
+ -- and an `update` that says `cancelled` reverses nothing in the ledger. A
61
+ -- posted invoice is corrected by a credit note: a `sale_credit_note` or
62
+ -- `purchase_credit_note` naming it in `reversed_document_id`, posted by the
63
+ -- same `post_document()`, whose entry is the mirror of the first. That path
64
+ -- exists, is tested below, and is the only one.
65
+ --
66
+ -- **Nobody is exempt, because nobody needs to be.** Nothing in this file asks
67
+ -- who the caller is. `post_document()` passes because of *when* it writes, the
68
+ -- matching because of *what* it writes, `taxes_reach_draft_lines` and
69
+ -- `contacts_language_reaches_drafts` because they only ever touched drafts.
70
+ -- One exemption is a fact rather than a privilege: when the *company* is being
71
+ -- deleted the cascade removes its documents, and a guard that refused would
72
+ -- make a company undeletable. The company's row is already gone when the
73
+ -- cascade arrives, which is what the guard looks at.
74
+ --
75
+ -- **Nobody is born posted either.** A document inserted with a state that is
76
+ -- not `draft`, or a line inserted under one, is refused to everybody —
77
+ -- `document_born_posted` — the installer and an administrator of the instance
78
+ -- included. Holding `documents.post` is the right to call `post_document()`,
79
+ -- not to write an invoice it never saw.
80
+ --
81
+ -- One thing does bring documents that are already posted: `import_company()`,
82
+ -- loading a company from an archive. An exemption for it was considered — the
83
+ -- insert, and the insert only, open to whoever may load a company — and then
84
+ -- withdrawn, because the import does not need one: it switches the triggers of
85
+ -- the tables it fills off, by name, inside its own transaction, behind its own
86
+ -- guard, and switches them back on. That is the rule this file sets for a
87
+ -- backfill, applied by a function: the guard is stepped around in one place,
88
+ -- where a reviewer reads it, and asks nobody who they are. Two other ways were
89
+ -- looked at and dropped. Going through a draft — the order the books were
90
+ -- written in — is not faithful to the cent: a draft line takes its snapshot and
91
+ -- its amounts from the tax *as it stands*. And a criterion of fact, "the line
92
+ -- arrives in the transaction that created its document", reads `xmin` and stops
93
+ -- being true at the first savepoint.
94
+ --
95
+ -- What arrives that way is then frozen like everything else, for the
96
+ -- administrator who loaded it too.
97
+ --
98
+ -- **The guards read as the schema, not as the caller.** Both are `security
99
+ -- definer`, and the reason was found by a test rather than foreseen: a guard
100
+ -- that asks "is this document still a draft?" or "is the company still there?"
101
+ -- under the caller's row level security is answered *no row* by whoever cannot
102
+ -- read the table — a machine key cannot read `companies` — and "no row" was
103
+ -- the answer that let a delete through. What a guard decides must not depend
104
+ -- on what the person it is guarding against is allowed to see. They write
105
+ -- nothing; `auth.uid()`, the key and the installer's setting are the session's
106
+ -- and read the same either way.
107
+ --
108
+ -- A later migration that must restate posted rows — a backfill — will be
109
+ -- refused by this guard, and that is intended: it has to disable the trigger
110
+ -- by name, in its own file, where a reviewer reads it.
111
+ --
112
+ -- `document_line_tax_frozen` is folded into this: one guard on a line, not
113
+ -- two. `document_lines_snapshot_tax()` keeps writing the snapshot of a draft
114
+ -- and no longer refuses anything, since nothing reaches it on a posted line.
115
+ -- `documents_guard_language` stays as it is — it fires first, and its sentence
116
+ -- is the better one for what it refuses.
117
+ --
118
+ -- What this does not close, and it is the larger half: **a posted entry can
119
+ -- still be deleted, emptied of its lines, or set back to `draft` while its
120
+ -- period is open.** `entries_guard_period` protects a locked period and
121
+ -- nothing protects an open one. An entry produced by a document is now held
122
+ -- by it — deleting it would null `documents.entry_id`, which this guard
123
+ -- refuses — but an entry keyed by hand, or a payment's, is not.
124
+
125
+ -- ---------------------------------------------------------------------------
126
+ -- 1. What a document has been settled by, as a figure that can be asked for
127
+ -- ---------------------------------------------------------------------------
128
+
129
+ create or replace function document_amount_paid(p_document_id uuid)
130
+ returns numeric
131
+ language sql
132
+ stable
133
+ set search_path = public, pg_temp
134
+ as $$
135
+ select coalesce((
136
+ select sum(case
137
+ when l.amount_currency is null then l.matched_amount
138
+ else round_amount(l.matched_amount * l.amount_currency
139
+ / nullif(abs(l.debit - l.credit), 0),
140
+ rounding_of(d.company_id, d.currency_code))
141
+ end)
142
+ from entry_lines l
143
+ join accounts a on a.id = l.account_id
144
+ where l.entry_id = d.entry_id
145
+ and a.reconcilable
146
+ and a.account_type in ('asset_receivable', 'liability_payable')
147
+ ), 0)
148
+ from documents d
149
+ where d.id = p_document_id;
150
+ $$;
151
+
152
+ comment on function document_amount_paid(uuid) is
153
+ 'What a document has been settled by: the matched amounts on the third-party lines of its entry, in the document''s currency. The one definition — documents_refresh_amount_paid() writes it and documents_guard_posted() accepts no other figure.';
154
+
155
+ revoke execute on function document_amount_paid(uuid) from public, anon;
156
+ grant execute on function document_amount_paid(uuid) to authenticated, service_role;
157
+
158
+ create or replace function documents_refresh_amount_paid(p_document_id uuid)
159
+ returns void
160
+ language plpgsql
161
+ as $$
162
+ begin
163
+ -- The statement names amount_paid so that documents_refresh_payment_state,
164
+ -- which watches that column, fires in turn.
165
+ update documents d
166
+ set amount_paid = document_amount_paid(d.id)
167
+ where d.id = p_document_id
168
+ and d.entry_id is not null;
169
+ end;
170
+ $$;
171
+
172
+ comment on column documents.amount_paid is
173
+ 'Derived from reconciliations on the third-party lines of the document''s entry: document_amount_paid(). Once the document is posted, any other figure is refused.';
174
+
175
+ -- ---------------------------------------------------------------------------
176
+ -- 2. The document
177
+ -- ---------------------------------------------------------------------------
178
+
179
+ create or replace function documents_guard_posted()
180
+ returns trigger
181
+ language plpgsql
182
+ security definer
183
+ set search_path = public, pg_temp
184
+ as $$
185
+ declare
186
+ -- What may still move once the state has left `draft`. A closed list: a
187
+ -- column that is not named here is frozen, including one that does not
188
+ -- exist yet.
189
+ c_still_moves constant text[] := array[
190
+ 'amount_paid', 'amount_residual', 'payment_state',
191
+ 'sent_at', 'peppol_status', 'peppol_message_id',
192
+ 'updated_at'
193
+ ];
194
+ v_moved text[];
195
+ begin
196
+ if tg_op = 'INSERT' then
197
+ if new.state <> 'draft' then
198
+ raise exception 'document_born_posted: a document is written as a draft and posted by post_document(). One that is already % arrives with a company being loaded, by import_company(), and in no other way.',
199
+ new.state
200
+ using errcode = '55006';
201
+ end if;
202
+ return new;
203
+ end if;
204
+
205
+ if tg_op = 'DELETE' then
206
+ if old.state = 'draft'
207
+ or not exists (select 1 from companies c where c.id = old.company_id) then
208
+ return old;
209
+ end if;
210
+ raise exception 'document_posted: % % was issued and cannot be deleted. It is undone by a credit note that names it.',
211
+ old.doc_type, coalesce(old.number, old.id::text)
212
+ using errcode = '55006';
213
+ end if;
214
+
215
+ if old.state = 'draft' then
216
+ -- The one transition that produces an entry has to have produced one.
217
+ if new.state = 'posted'
218
+ and not exists (select 1 from entries e where e.id = new.entry_id and e.state = 'posted') then
219
+ raise exception 'document_posted_without_entry: % has no posted entry. A document is posted by post_document(), which builds its entry and posts it first.',
220
+ coalesce(new.number, new.id::text)
221
+ using errcode = '55006';
222
+ end if;
223
+ return new;
224
+ end if;
225
+
226
+ if new.state is distinct from old.state then
227
+ raise exception 'document_posted: % % is % and stays so. It is undone by a credit note that names it, never by changing its state to %.',
228
+ old.doc_type, coalesce(old.number, old.id::text), old.state, new.state
229
+ using errcode = '55006';
230
+ end if;
231
+
232
+ select array_agg(n.key order by n.key)
233
+ into v_moved
234
+ from jsonb_each(to_jsonb(new)) n
235
+ join jsonb_each(to_jsonb(old)) o on o.key = n.key
236
+ where n.value is distinct from o.value
237
+ and n.key <> all (c_still_moves);
238
+
239
+ if v_moved is not null then
240
+ raise exception 'document_posted: % % was issued and keeps its % (%). What produced an entry does not change after it; credit it and issue another.',
241
+ old.doc_type, coalesce(old.number, old.id::text),
242
+ case when array_length(v_moved, 1) = 1 then 'value of' else 'values of' end,
243
+ array_to_string(v_moved, ', ')
244
+ using errcode = '55006';
245
+ end if;
246
+
247
+ if new.amount_paid is distinct from old.amount_paid
248
+ and new.amount_paid is distinct from document_amount_paid(new.id) then
249
+ raise exception 'document_amount_paid_is_derived: % has been settled by %, which is what its matching says. The figure is never keyed.',
250
+ coalesce(old.number, old.id::text), document_amount_paid(new.id)
251
+ using errcode = '55006';
252
+ end if;
253
+
254
+ if new.payment_state is distinct from old.payment_state
255
+ and new.amount_paid is not distinct from old.amount_paid then
256
+ raise exception 'document_payment_state_is_derived: the settlement of % follows from what was matched against it, and is never keyed.',
257
+ coalesce(old.number, old.id::text)
258
+ using errcode = '55006';
259
+ end if;
260
+
261
+ return new;
262
+ end;
263
+ $$;
264
+
265
+ comment on function documents_guard_posted() is
266
+ 'Once a document has left draft: its state does not change, it is not deleted, and no column moves but the closed list of what happens to a document after it is issued — amount_paid (to the figure the matching gives, and no other), payment_state, sent_at, peppol_status, peppol_message_id. Refuses document_posted, by name, to everybody. Becoming posted requires an entry, and nobody inserts a document that is already posted (document_born_posted): one arrives that way only with a company loaded by import_company(), which switches this guard off by name for the time of the load.';
267
+
268
+ create trigger documents_guard_posted
269
+ before insert or update or delete on documents
270
+ for each row execute function documents_guard_posted();
271
+
272
+ -- A trigger body is invoked by its table, never called.
273
+ revoke execute on function documents_guard_posted() from public, anon, authenticated, service_role;
274
+
275
+ -- ---------------------------------------------------------------------------
276
+ -- 3. Its lines
277
+ --
278
+ -- Every column, an insert and a delete: a line of an issued document is the
279
+ -- line that was issued. `updated_at` is the one column a trigger of this
280
+ -- table writes on its own, and an update that changes nothing else is not a
281
+ -- change.
282
+ -- ---------------------------------------------------------------------------
283
+
284
+ create or replace function document_lines_guard_posted()
285
+ returns trigger
286
+ language plpgsql
287
+ security definer
288
+ set search_path = public, pg_temp
289
+ as $$
290
+ declare
291
+ v_state doc_state;
292
+ v_number text;
293
+ v_type doc_type;
294
+ v_moved text[];
295
+ begin
296
+ select d.state, d.number, d.doc_type into v_state, v_number, v_type
297
+ from documents d
298
+ where d.id = coalesce(new.document_id, old.document_id);
299
+
300
+ -- No document: it is being deleted, and its lines with it. Whether *that*
301
+ -- was allowed is the question documents_guard_posted() answered.
302
+ if not found or v_state = 'draft' then
303
+ -- A line does not leave a posted document for a draft either.
304
+ if tg_op = 'UPDATE' and new.document_id is distinct from old.document_id then
305
+ select d.state, d.number, d.doc_type into v_state, v_number, v_type
306
+ from documents d where d.id = old.document_id;
307
+ if found and v_state <> 'draft' then
308
+ raise exception 'document_posted: a line of % % was issued with it and stays on it.',
309
+ v_type, coalesce(v_number, old.document_id::text)
310
+ using errcode = '55006';
311
+ end if;
312
+ end if;
313
+ return coalesce(new, old);
314
+ end if;
315
+
316
+ if tg_op = 'DELETE' then
317
+ if not exists (select 1 from companies c where c.id = old.company_id) then
318
+ return old;
319
+ end if;
320
+ raise exception 'document_posted: line % of % % was issued and cannot be deleted. Credit the document and issue another.',
321
+ old.sequence, v_type, coalesce(v_number, old.document_id::text)
322
+ using errcode = '55006';
323
+ end if;
324
+
325
+ if tg_op = 'INSERT' then
326
+ raise exception 'document_posted: % % was issued with the lines it has, and takes no other. Credit it and issue another.',
327
+ v_type, coalesce(v_number, new.document_id::text)
328
+ using errcode = '55006';
329
+ end if;
330
+
331
+ select array_agg(n.key order by n.key)
332
+ into v_moved
333
+ from jsonb_each(to_jsonb(new)) n
334
+ join jsonb_each(to_jsonb(old)) o on o.key = n.key
335
+ where n.value is distinct from o.value
336
+ and n.key <> 'updated_at';
337
+
338
+ if v_moved is not null then
339
+ raise exception 'document_posted: line % of % % was issued and keeps its % (%). What produced an entry does not change after it; credit the document and issue another.',
340
+ old.sequence, v_type, coalesce(v_number, old.document_id::text),
341
+ case when array_length(v_moved, 1) = 1 then 'value of' else 'values of' end,
342
+ array_to_string(v_moved, ', ')
343
+ using errcode = '55006';
344
+ end if;
345
+ return new;
346
+ end;
347
+ $$;
348
+
349
+ comment on function document_lines_guard_posted() is
350
+ 'Once a document has left draft, its lines are the lines that were issued: no insert, no delete, no column changed. Refuses document_posted, by name, to everybody.';
351
+
352
+ -- Named to fire before the other `before` triggers of the table, which fire in
353
+ -- the order of their names: a posted line is refused by this guard, by name,
354
+ -- and not by whatever an older trigger trips over on the way — and a derived
355
+ -- column keyed on a posted line is judged as it was keyed, before the line's
356
+ -- own trigger writes the right figure back over it.
357
+ create trigger document_lines_00_guard_posted
358
+ before insert or update or delete on document_lines
359
+ for each row execute function document_lines_guard_posted();
360
+
361
+ -- ---------------------------------------------------------------------------
362
+ -- 3b. The totals of a posted document are not recomputed
363
+ --
364
+ -- They were derived from the lines for as long as the lines could move, by a
365
+ -- trigger that fired on every write of a line whatever the state. The lines of
366
+ -- a posted document no longer move, so there is nothing left for it to do
367
+ -- there — and what it did do, before this file, was restate the totals of a
368
+ -- sent invoice from whatever its lines had been changed to. It now acts on
369
+ -- drafts. `documents_refresh_totals()` itself is unchanged and still answers
370
+ -- for whoever calls it.
371
+ -- ---------------------------------------------------------------------------
372
+
373
+ create or replace function document_lines_refresh_totals()
374
+ returns trigger
375
+ language plpgsql
376
+ as $$
377
+ declare
378
+ v_document uuid := coalesce(new.document_id, old.document_id);
379
+ begin
380
+ if not exists (select 1 from documents d where d.id = v_document and d.state = 'draft') then
381
+ return null;
382
+ end if;
383
+ -- The allocator writes its shares back through this same trigger, and what it
384
+ -- wrote is already the answer. Only the outermost write allocates: a second
385
+ -- pass would be work for nothing, and in a currency whose decimals the column
386
+ -- cannot hold — `amount_untaxed` is `numeric(16, 2)`, which is a gap of its
387
+ -- own — a share that comes back rounded would never compare equal and the
388
+ -- two would call each other for ever.
389
+ if pg_trigger_depth() <= 1 then
390
+ perform documents_allocate_included_tax(v_document);
391
+ end if;
392
+ perform documents_refresh_totals(v_document);
393
+ return null;
394
+ end;
395
+ $$;
396
+
397
+ comment on function document_lines_refresh_totals() is
398
+ 'After a line of a draft moves: shares out the base of every tax group quoted with its tax in it, then refreshes the three totals of the document. A document that is no longer a draft keeps the totals it was posted, or loaded, with.';
399
+
400
+ revoke execute on function document_lines_guard_posted() from public, anon, authenticated, service_role;
401
+
402
+ -- ---------------------------------------------------------------------------
403
+ -- 4. One guard on a line, not two
404
+ --
405
+ -- `20260918141107` as it was, less the branch that refused: nothing reaches it
406
+ -- on a posted line any more. It writes the snapshot of a draft, and of a line
407
+ -- that arrives.
408
+ -- ---------------------------------------------------------------------------
409
+
410
+ create or replace function document_lines_snapshot_tax()
411
+ returns trigger
412
+ language plpgsql
413
+ as $$
414
+ declare
415
+ v_state doc_state;
416
+ begin
417
+ select d.state into v_state from documents d where d.id = new.document_id;
418
+ if tg_op = 'UPDATE' and v_state <> 'draft' then
419
+ return new;
420
+ end if;
421
+
422
+ if new.line_type <> 'product' or new.tax_id is null then
423
+ new.vat_category := null;
424
+ new.vat_rate := null;
425
+ return new;
426
+ end if;
427
+
428
+ select t.vat_category,
429
+ case when t.amount_type = 'percent' then t.amount end
430
+ into new.vat_category, new.vat_rate
431
+ from taxes t where t.id = new.tax_id;
432
+ return new;
433
+ end;
434
+ $$;
435
+
436
+ comment on function document_lines_snapshot_tax() is
437
+ 'Writes BT-151 and BT-152 on a line from its tax for as long as the document is a draft. Once it is not, document_lines_guard_posted() refuses any change to the line, these two columns included.';