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,284 @@
1
+ -- Ekwo OS — the schema grants its own rights.
2
+ --
3
+ -- Until this file, nothing in `supabase/migrations` gave `anon` or
4
+ -- `authenticated` a single privilege on a single table. The schema worked
5
+ -- anyway, because a Supabase project carries default privileges on `public`
6
+ -- that hand `all` on every new table, sequence and function to `anon`,
7
+ -- `authenticated` and `service_role`. Row level security then decided who saw
8
+ -- what, and the arrangement looked sound.
9
+ --
10
+ -- Two things were wrong with it.
11
+ --
12
+ -- The first is a hole. Those defaults give `anon` — the role behind the
13
+ -- publishable key that any visitor holds — INSERT, UPDATE and DELETE on every
14
+ -- table of the ledger. Only row level security stands between an anonymous
15
+ -- request and the books. That is one layer where the doctrine of this project
16
+ -- says there are two: `anon` reaches the eight policy helpers and nothing
17
+ -- else (`20260911210131`), and "nothing else" has to include the tables.
18
+ --
19
+ -- The second is a dependency nobody declared. The first real end-to-end run,
20
+ -- on 14 September 2026, dropped and recreated `public` on a throwaway
21
+ -- project. The migrations replayed, `ekwo doctor` reported a healthy
22
+ -- installation, and the first read through PostgREST answered "permission
23
+ -- denied for table companies" — because the default privileges live in
24
+ -- `pg_default_acl`, keyed by the schema, and had gone with it. An
25
+ -- installation whose access rights come from something the installer never
26
+ -- wrote is an installation that cannot be reproduced.
27
+ --
28
+ -- So the privileges are declared here, by name, table by table and view by
29
+ -- view. `grant all on all tables` is not used anywhere: a wildcard is how a
30
+ -- table added next year silently becomes writable by a role nobody thought
31
+ -- about. From this migration on, a migration that creates a table, a view or
32
+ -- a function grants it in the same file, beside the `revoke execute ... from
33
+ -- public` that is already compulsory. `tests/grants.test.ts` compares the
34
+ -- catalogue to the inventory generated from the migrations and fails when the
35
+ -- two disagree, and `ekwo doctor` asks the same question of a live database.
36
+ --
37
+ -- What is deliberately *not* decided here: which companies a role may see.
38
+ -- That is row level security, and every policy of this schema is unchanged.
39
+ -- A grant says which verbs a role may attempt; a policy says on which rows
40
+ -- they succeed. This file is only the first half, and it is the half that was
41
+ -- being borrowed.
42
+
43
+ -- ---------------------------------------------------------------------------
44
+ -- 1. The schema itself
45
+ --
46
+ -- A Supabase project already grants this. Saying it again costs nothing and
47
+ -- is what makes a bare Postgres — the reset above, a self-hosted instance, the
48
+ -- test harness — reach the same state from the migrations alone.
49
+ -- ---------------------------------------------------------------------------
50
+
51
+ grant usage on schema public to anon, authenticated, service_role;
52
+
53
+ -- ---------------------------------------------------------------------------
54
+ -- 2. Everything the project's defaults handed out goes back
55
+ --
56
+ -- `revoke all on all tables` is the safe direction of a wildcard: it can only
57
+ -- close. It takes back the blanket privileges an existing installation
58
+ -- received at creation, including the write access `anon` was never meant to
59
+ -- have, and the grants below then re-open exactly what is needed.
60
+ --
61
+ -- The `alter default privileges` lines stop the same thing happening to the
62
+ -- next table. They are scoped to the role running the migration, which on a
63
+ -- Supabase project is `postgres` — the role that owns the entries. A default
64
+ -- privilege set by another role is not reachable from here and would show up
65
+ -- as an extra grant on the first table created after it, which is what the
66
+ -- invariant test and the doctor are for.
67
+ --
68
+ -- The function line closes Ekwo's own backstop, not Supabase's:
69
+ -- `20260911210131` granted EXECUTE on future functions to `authenticated` and
70
+ -- `service_role` by default privilege, and that is the same hidden mechanism
71
+ -- one level down. Functions created before today keep the grants they were
72
+ -- given — a privilege already in `proacl` is not touched by a change of
73
+ -- default — so nothing that works stops working. A function created after
74
+ -- today is granted in its own migration or it is reachable by nobody.
75
+ --
76
+ -- The `revoke execute on functions from public, anon` default of that same
77
+ -- migration stays exactly as it is. It closes rather than opens, and it is
78
+ -- the reason a new function is not published as an anonymous RPC endpoint.
79
+ -- ---------------------------------------------------------------------------
80
+
81
+ revoke all on all tables in schema public from anon, authenticated, service_role;
82
+ revoke all on all sequences in schema public from anon, authenticated, service_role;
83
+
84
+ alter default privileges in schema public revoke all on tables from anon, authenticated, service_role;
85
+ alter default privileges in schema public revoke all on sequences from anon, authenticated, service_role;
86
+ alter default privileges in schema public revoke execute on functions from authenticated, service_role;
87
+
88
+ -- ---------------------------------------------------------------------------
89
+ -- 3. The tables a signed-in user writes
90
+ --
91
+ -- These twenty-six are the ones whose policies allow more than reading: each
92
+ -- carries a policy `for all` — or, for `companies`, `company_members` and
93
+ -- `instance_admins`, one policy per command — so the four verbs are the ones
94
+ -- row level security is already prepared to judge. The grant and the policy
95
+ -- say the same thing about the same table, which is the property the
96
+ -- invariant test checks.
97
+ --
98
+ -- DELETE is granted on `entries`, `entry_lines`, `documents`,
99
+ -- `document_lines`, `payments` and `reconciliations` on purpose. Deleting a
100
+ -- *draft* is an ordinary act of bookkeeping; deleting a posted entry is
101
+ -- refused by `entries_guard_period` and by the period lock, not by a missing
102
+ -- privilege. Taking DELETE away here would break the draft and leave the
103
+ -- posted entry exactly as protected as it already is.
104
+ --
105
+ -- `service_role` gets the same set. It is the backend key: it bypasses row
106
+ -- level security, so its table rights are the only limit it has, and there is
107
+ -- no reason for that limit to be wider than a person's.
108
+ -- ---------------------------------------------------------------------------
109
+
110
+ grant select, insert, update, delete on table
111
+ accounts,
112
+ analytic_axes,
113
+ analytic_values,
114
+ attachments,
115
+ bank_accounts,
116
+ bank_statements,
117
+ bank_transactions,
118
+ companies,
119
+ company_members,
120
+ company_packs,
121
+ contacts,
122
+ document_lines,
123
+ documents,
124
+ entries,
125
+ entry_line_analytics,
126
+ entry_lines,
127
+ fiscal_years,
128
+ instance,
129
+ instance_admins,
130
+ journals,
131
+ payments,
132
+ products,
133
+ reconciliations,
134
+ tax_postings,
135
+ taxes,
136
+ user_preferences
137
+ to authenticated, service_role;
138
+
139
+ -- ---------------------------------------------------------------------------
140
+ -- 4. The reference tables, which a client reads and an installation writes
141
+ --
142
+ -- Eighteen tables a country pack and a release fill: the chart templates, the
143
+ -- taxes and their postings, the declaration boxes, the statement schemes, the
144
+ -- currencies and their rates, the capabilities and the modules this release
145
+ -- carries. Their policies allow SELECT and nothing else, and the writer is
146
+ -- `ekwo migrate` on the owner's connection or `install_country_template()`
147
+ -- running as definer. No INSERT, no UPDATE, no DELETE: a client that could
148
+ -- edit the chart of accounts of a country could edit it for every company of
149
+ -- the installation at once.
150
+ -- ---------------------------------------------------------------------------
151
+
152
+ grant select on table
153
+ account_templates,
154
+ capabilities,
155
+ chart_templates,
156
+ country_defaults,
157
+ country_packs,
158
+ currencies,
159
+ currency_rates,
160
+ journal_templates,
161
+ legal_mention_templates,
162
+ modules,
163
+ role_capabilities,
164
+ statement_line_rules,
165
+ statement_line_templates,
166
+ statement_templates,
167
+ tax_posting_templates,
168
+ tax_report_box_templates,
169
+ tax_report_templates,
170
+ tax_templates
171
+ to authenticated, service_role;
172
+
173
+ -- ---------------------------------------------------------------------------
174
+ -- 5. The tables only a function writes
175
+ --
176
+ -- Five tables whose rows exist because a `security definer` function made
177
+ -- them, and which no client may write directly. `api_keys` holds a sha256 and
178
+ -- is issued by `create_api_key()`; `company_invitations` by `invite_member()`
179
+ -- and consumed by `accept_invitation()`; `company_modules` by
180
+ -- `enable_module()`; and the two counters are advanced by
181
+ -- `next_entry_number()` and `next_matching_number()`, which is the whole
182
+ -- reason those two became definer in `20260911173100`. A client with UPDATE
183
+ -- on `journal_sequences` could rewind the numbering of a journal, which in
184
+ -- several countries is the offence the numbering rule exists to prevent.
185
+ -- ---------------------------------------------------------------------------
186
+
187
+ grant select on table
188
+ api_keys,
189
+ company_invitations,
190
+ company_modules,
191
+ journal_sequences,
192
+ matching_sequences
193
+ to authenticated, service_role;
194
+
195
+ -- ---------------------------------------------------------------------------
196
+ -- 6. The audit trail: SELECT, and nothing else, for anyone
197
+ --
198
+ -- `audit_log` is append-only by trigger for every role including its owner,
199
+ -- and its only policy is a SELECT. UPDATE and DELETE are therefore refused
200
+ -- twice over, which is the point: the trigger is the guarantee and the
201
+ -- missing privilege is the statement of intent. INSERT is not granted either
202
+ -- — the rows are written by `audit_record()`, a definer function the triggers
203
+ -- call, and a client that could insert its own could write a history that
204
+ -- never happened.
205
+ -- ---------------------------------------------------------------------------
206
+
207
+ grant select on table audit_log to authenticated, service_role;
208
+
209
+ -- ---------------------------------------------------------------------------
210
+ -- 7. The views
211
+ --
212
+ -- All four are `security_invoker`, so a reader needs SELECT on the view *and*
213
+ -- on the tables under it, and row level security is judged on the reader
214
+ -- rather than on the owner. The grants above give the second half; this gives
215
+ -- the first.
216
+ -- ---------------------------------------------------------------------------
217
+
218
+ grant select on table
219
+ document_header,
220
+ document_legal_mentions,
221
+ document_line_items,
222
+ document_tax_summary
223
+ to authenticated, service_role;
224
+
225
+ -- ---------------------------------------------------------------------------
226
+ -- 8. Sequences: none, and on purpose
227
+ --
228
+ -- The schema has one, `audit_log_id_seq`, and it belongs to an identity
229
+ -- column of a table nobody but a definer function inserts into. An identity
230
+ -- column takes its next value without asking for USAGE on the sequence, so
231
+ -- there is nothing to grant and nothing that breaks by not granting it. A
232
+ -- migration that adds a `serial` or an identity column to a table a client
233
+ -- inserts into will need `grant usage on sequence …` in its own file.
234
+ -- ---------------------------------------------------------------------------
235
+
236
+ -- ---------------------------------------------------------------------------
237
+ -- 9. Functions: the trigger bodies stop being callable
238
+ --
239
+ -- The eighty-two functions a client may call already hold nominative grants,
240
+ -- given by the migration that created each of them. What was left over is the
241
+ -- twenty-nine whose return type is `trigger`. A trigger function is invoked
242
+ -- by the table it is attached to, not by a caller: PostgreSQL checks EXECUTE
243
+ -- when the trigger is *created*, never when it fires, so revoking it changes
244
+ -- nothing about the schema's behaviour and removes twenty-nine RPC endpoints
245
+ -- that answer "trigger functions can only be called as triggers" to anyone who
246
+ -- finds them. Four of them were already closed to `anon` and `authenticated`
247
+ -- by `20260914103412`; this completes the set and adds `service_role`.
248
+ -- ---------------------------------------------------------------------------
249
+
250
+ revoke execute on function
251
+ assert_may_close_year(),
252
+ assert_may_post_document(),
253
+ assert_may_post_entry(),
254
+ audit_changes(),
255
+ audit_entry_posting(),
256
+ audit_log_is_append_only(),
257
+ audit_state_change(),
258
+ bank_statements_recompute(),
259
+ bank_statements_refresh_balance(),
260
+ companies_default_bank_account_is_ours(),
261
+ companies_default_capital_currency(),
262
+ company_members_capabilities_known(),
263
+ currency_of_bank_account(),
264
+ currency_of_company(),
265
+ document_lines_amount_untaxed(),
266
+ document_lines_refresh_totals(),
267
+ document_lines_resolve_account(),
268
+ documents_default_payee_iban(),
269
+ documents_refresh_payment_state(),
270
+ entries_guard_kind(),
271
+ entries_guard_module(),
272
+ entries_guard_period(),
273
+ entries_refresh_totals(),
274
+ entry_lines_guard_period(),
275
+ fiscal_years_guard_closed(),
276
+ fiscal_years_no_overlap(),
277
+ locale_of_country_pack(),
278
+ reconciliations_refresh_lines(),
279
+ set_updated_at()
280
+ from public, anon, authenticated, service_role;
281
+
282
+ -- The rule of `supabase/migrations/README.md`, which this file obeys like any
283
+ -- other even though it creates no function.
284
+ revoke execute on all functions in schema public from public;
@@ -0,0 +1,237 @@
1
+ -- `pack_upgrade()` becomes `security definer`, so that it can write the line
2
+ -- it promises to write.
3
+ --
4
+ -- Found by the test that took the default privileges away from the harness.
5
+ -- `20260914103412` closed `audit_record()` to `anon` and `authenticated`: the
6
+ -- audit trail is written by the triggers, which are `security definer` and
7
+ -- therefore call it as the owner, and a client that could call it directly
8
+ -- could append a history that never happened. `pack_upgrade()` is the one
9
+ -- function in the schema that records its own line rather than leaving it to a
10
+ -- trigger — an upgrade is an act, not a row change — and it was `security
11
+ -- invoker`, so the call was made as the caller.
12
+ --
13
+ -- Nothing noticed, because `tests/helpers/db.ts` ended with `grant execute on
14
+ -- all functions in schema public to authenticated`, which handed back the
15
+ -- EXECUTE that migration had just taken away. On a real project the grant does
16
+ -- not exist and the first owner who runs `ekwo pack upgrade` through PostgREST
17
+ -- gets `permission denied for function audit_record` after the upgrade has
18
+ -- already been applied — the writes are committed, the trail is not.
19
+ --
20
+ -- The fix is the one its peers use. `enable_module()`, `invite_member()`,
21
+ -- `create_api_key()` and `accept_invitation()` are all `security definer` with
22
+ -- an explicit membership test, and this function already carries the same
23
+ -- test: it refuses a caller without `company.write` on the company it was
24
+ -- given, by name, before it touches anything. Definer moves who the writes are
25
+ -- made as; it does not move who is allowed to ask, and the answer to that
26
+ -- question is unchanged.
27
+ --
28
+ -- The body is the published one, word for word, with `security definer` and a
29
+ -- fixed `search_path` added — a definer function that resolves its own names
30
+ -- through the caller's `search_path` is the classic way to hand one away.
31
+
32
+ create or replace function pack_upgrade(
33
+ p_company_id uuid,
34
+ p_country char(2) default null,
35
+ p_apply boolean default false
36
+ )
37
+ returns jsonb
38
+ language plpgsql
39
+ security definer
40
+ set search_path = public, pg_temp
41
+ as $$
42
+ declare
43
+ v_country char(2);
44
+ v_chart text;
45
+ v_from text;
46
+ v_to text;
47
+ v_applied jsonb := '[]'::jsonb;
48
+ v_listed jsonb := '[]'::jsonb;
49
+ v_refused jsonb := '[]'::jsonb;
50
+ d record;
51
+ v_tax_id uuid;
52
+ v_template tax_templates%rowtype;
53
+ begin
54
+ select coalesce(p_country, c.country) into v_country
55
+ from companies c where c.id = p_company_id;
56
+ if v_country is null then
57
+ raise exception 'unknown_company: %', p_company_id;
58
+ end if;
59
+
60
+ if auth.uid() is not null and not has_capability(p_company_id, 'company.write') then
61
+ raise exception 'not_allowed: upgrading a country pack needs company.write';
62
+ end if;
63
+
64
+ select cp.version, cp.chart_code into v_from, v_chart
65
+ from company_packs cp
66
+ where cp.company_id = p_company_id and cp.country = v_country;
67
+ if v_chart is null then
68
+ raise exception 'no_pack_installed: company % holds no % pack, so there is nothing to upgrade from', p_company_id, v_country;
69
+ end if;
70
+
71
+ select version into v_to from country_packs where country = v_country;
72
+ if v_to is null then
73
+ raise exception 'no_pack_loaded: this installation holds no % pack. Apply the seeds of this release first.', v_country;
74
+ end if;
75
+
76
+ for d in select * from pack_upgrade_diff(p_company_id, v_country) loop
77
+ -- Never, whatever the caller asked. An upgrade adds and closes; it does
78
+ -- not take a row out of a company's books.
79
+ if d.change = 'company_only' then
80
+ v_refused := v_refused || jsonb_build_object('object', d.object, 'key', d.key,
81
+ 'change', d.change, 'rule', d.rule,
82
+ 'detail', d.detail);
83
+ continue;
84
+ end if;
85
+
86
+ if d.rule = 'review' and not p_apply then
87
+ v_listed := v_listed || jsonb_build_object('object', d.object, 'key', d.key,
88
+ 'change', d.change, 'rule', d.rule,
89
+ 'detail', d.detail);
90
+ continue;
91
+ end if;
92
+
93
+ if d.object = 'account' and d.change = 'missing' then
94
+ insert into accounts (company_id, code, name, name_i18n, statement_hint, account_type, reconcilable)
95
+ select p_company_id, t.code, label_for(t.name, t.name_i18n, preferred_languages(p_company_id)),
96
+ t.name_i18n, t.statement_hint, t.account_type, t.reconcilable
97
+ from account_templates t
98
+ where t.country = v_country and t.chart_code = v_chart and t.code = d.key
99
+ on conflict (company_id, code) do nothing;
100
+
101
+ elsif d.object = 'account' and d.change = 'differs' then
102
+ update accounts a
103
+ set name = label_for(t.name, t.name_i18n, preferred_languages(p_company_id)),
104
+ name_i18n = t.name_i18n,
105
+ account_type = t.account_type
106
+ from account_templates t
107
+ where t.country = v_country and t.chart_code = v_chart and t.code = a.code
108
+ and a.company_id = p_company_id and a.code = d.key;
109
+
110
+ elsif d.object = 'journal' and d.change = 'missing' then
111
+ insert into journals (company_id, code, name, journal_type)
112
+ select p_company_id, t.code, t.name, t.journal_type
113
+ from journal_templates t
114
+ where t.country = v_country and t.code = d.key
115
+ on conflict (company_id, code) do nothing;
116
+
117
+ elsif d.object = 'journal' and d.change = 'differs' then
118
+ update journals j
119
+ set name = t.name, journal_type = t.journal_type
120
+ from journal_templates t
121
+ where t.country = v_country and t.code = j.code
122
+ and j.company_id = p_company_id and j.code = d.key;
123
+
124
+ elsif d.object = 'tax' and d.change = 'missing' then
125
+ select * into v_template from tax_templates where country = v_country and code = d.key;
126
+ insert into taxes (company_id, code, name, description, amount_type, amount,
127
+ applies_to, treatment, country, valid_from, valid_to,
128
+ legal_reference, vat_category, exemption_code, sequence,
129
+ tax_kind, recoverable, jurisdiction, price_include,
130
+ cash_basis, cash_basis_transition_account_id)
131
+ values (p_company_id, v_template.code, v_template.name, v_template.description,
132
+ v_template.amount_type, v_template.amount, v_template.applies_to,
133
+ v_template.treatment, v_country, v_template.valid_from, v_template.valid_to,
134
+ v_template.legal_reference, v_template.vat_category, v_template.exemption_code,
135
+ v_template.sequence, v_template.tax_kind, v_template.recoverable,
136
+ v_template.jurisdiction, v_template.price_include, v_template.cash_basis,
137
+ account_id_by_code(p_company_id, v_template.cash_basis_transition_account_code))
138
+ on conflict (company_id, code) do nothing
139
+ returning id into v_tax_id;
140
+
141
+ if v_tax_id is not null then
142
+ insert into tax_postings (tax_id, company_id, document_kind, posting_type,
143
+ factor_percent, account_id, declaration_box,
144
+ box_factor_percent, report_code, sequence)
145
+ select v_tax_id, p_company_id, tp.document_kind, tp.posting_type,
146
+ tp.factor_percent, account_id_by_code(p_company_id, tp.account_code),
147
+ tp.declaration_box, tp.box_factor_percent, tp.report_code, tp.sequence
148
+ from tax_posting_templates tp
149
+ where tp.tax_template_id = v_template.id
150
+ order by tp.sequence;
151
+ end if;
152
+
153
+ elsif d.object = 'tax' and d.change = 'valid_to' then
154
+ update taxes x
155
+ set valid_to = t.valid_to
156
+ from tax_templates t
157
+ where t.country = v_country and t.code = x.code
158
+ and x.company_id = p_company_id and x.code = d.key;
159
+
160
+ elsif d.object = 'tax' and d.change = 'differs' then
161
+ update taxes x
162
+ set name = t.name, description = t.description, amount = t.amount,
163
+ amount_type = t.amount_type, applies_to = t.applies_to,
164
+ treatment = t.treatment, valid_from = t.valid_from,
165
+ legal_reference = t.legal_reference, vat_category = t.vat_category,
166
+ exemption_code = t.exemption_code, tax_kind = t.tax_kind,
167
+ recoverable = t.recoverable, jurisdiction = t.jurisdiction,
168
+ price_include = t.price_include, cash_basis = t.cash_basis
169
+ from tax_templates t
170
+ where t.country = v_country and t.code = x.code
171
+ and x.company_id = p_company_id and x.code = d.key;
172
+
173
+ elsif d.object = 'tax_posting' and d.change = 'differs' then
174
+ select id into v_tax_id from taxes where company_id = p_company_id and code = d.key;
175
+ delete from tax_postings where tax_id = v_tax_id;
176
+ insert into tax_postings (tax_id, company_id, document_kind, posting_type,
177
+ factor_percent, account_id, declaration_box,
178
+ box_factor_percent, report_code, sequence)
179
+ select v_tax_id, p_company_id, tp.document_kind, tp.posting_type,
180
+ tp.factor_percent, account_id_by_code(p_company_id, tp.account_code),
181
+ tp.declaration_box, tp.box_factor_percent, tp.report_code, tp.sequence
182
+ from tax_posting_templates tp
183
+ join tax_templates t on t.id = tp.tax_template_id
184
+ where t.country = v_country and t.code = d.key
185
+ order by tp.sequence;
186
+
187
+ else
188
+ -- A difference this function does not know how to apply is listed
189
+ -- rather than guessed at. Raising here would make a new kind of
190
+ -- difference break every upgrade.
191
+ v_listed := v_listed || jsonb_build_object('object', d.object, 'key', d.key,
192
+ 'change', d.change, 'rule', d.rule,
193
+ 'detail', d.detail);
194
+ continue;
195
+ end if;
196
+
197
+ v_applied := v_applied || jsonb_build_object('object', d.object, 'key', d.key,
198
+ 'change', d.change, 'rule', d.rule,
199
+ 'detail', d.detail);
200
+ end loop;
201
+
202
+ -- The version moves only when nothing is left waiting. A company that still
203
+ -- holds a difference it has not decided on has not finished upgrading, and
204
+ -- saying otherwise would hide the difference at the next run.
205
+ if jsonb_array_length(v_listed) = 0 then
206
+ update company_packs
207
+ set version = v_to, upgraded_at = now()
208
+ where company_id = p_company_id and country = v_country;
209
+ end if;
210
+
211
+ perform audit_record(
212
+ p_company_id, 'company_packs', null, v_country, 'update', 'pack_upgraded',
213
+ jsonb_build_object('version', v_from),
214
+ jsonb_build_object('version', case when jsonb_array_length(v_listed) = 0 then v_to else v_from end,
215
+ 'pack_version', v_to,
216
+ 'chart_code', v_chart,
217
+ 'applied', v_applied,
218
+ 'listed', v_listed,
219
+ 'never_applied', v_refused));
220
+
221
+ return jsonb_build_object(
222
+ 'company_id', p_company_id,
223
+ 'country', v_country,
224
+ 'chart_code', v_chart,
225
+ 'from_version', v_from,
226
+ 'to_version', v_to,
227
+ 'version_moved', jsonb_array_length(v_listed) = 0,
228
+ 'applied', v_applied,
229
+ 'listed', v_listed,
230
+ 'never_applied', v_refused);
231
+ end;
232
+ $$;
233
+
234
+ comment on function pack_upgrade(uuid, char, boolean) is
235
+ 'Moves a company to the country pack version this installation holds: additions copied in, closed validities applied, everything else listed and left alone unless the caller asks for it. Records what it did in the audit trail. The recorded version moves only when nothing is left waiting. Definer, because the line it records goes through audit_record(), which no client may call; the caller still needs company.write on the company.';
236
+
237
+ revoke execute on all functions in schema public from public;