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
package/dist/doctor.js ADDED
@@ -0,0 +1,448 @@
1
+ /**
2
+ * `ekwo doctor` — the checks worth running on a live installation.
3
+ *
4
+ * Each one is something that is true of a healthy database and that nothing
5
+ * in the schema can enforce on its own: a table someone added without row
6
+ * level security, a migration that never landed, a membership row pointing at
7
+ * a user who has since been deleted, a bank statement whose declared closing
8
+ * balance does not match its lines.
9
+ *
10
+ * The doctor reads and reports. It never repairs: the fix for a missing
11
+ * policy is a migration, and the fix for an orphaned membership is a decision
12
+ * about who should have access, not a delete the installer guesses at.
13
+ */
14
+ import { compareSection, describeFinding } from './grants.js';
15
+ import { compareCatalogue, describeDifferences, installedSections, readExpectedObjects, readGrants, } from './inventory.js';
16
+ import { migrationGap } from './migrations.js';
17
+ import { scalar } from './sql.js';
18
+ export async function doctor(db, migrations, options = {}) {
19
+ const checks = [];
20
+ // Read once and handed to both: the inventory carries the objects a release
21
+ // defines and the privileges it grants on them, and reading the file twice
22
+ // would be two answers to one question.
23
+ const expected = options.expected ?? (await readExpectedObjects());
24
+ checks.push(await checkMigrations(db, migrations));
25
+ checks.push(await checkCatalogue(db, expected));
26
+ checks.push(await checkRowLevelSecurity(db));
27
+ checks.push(await checkPolicies(db));
28
+ checks.push(await checkGrants(db, expected));
29
+ checks.push(await checkOrphanMembers(db));
30
+ checks.push(await checkOrphanAdmins(db));
31
+ checks.push(await checkBankAccounts(db));
32
+ checks.push(await checkStatements(db));
33
+ checks.push(await checkPostedEntriesBalance(db));
34
+ checks.push(await checkAuditTrail(db));
35
+ return {
36
+ checks,
37
+ problems: checks.filter((c) => c.severity === 'problem').length,
38
+ warnings: checks.filter((c) => c.severity === 'warning').length,
39
+ };
40
+ }
41
+ async function checkMigrations(db, migrations) {
42
+ const gap = await migrationGap(db, migrations);
43
+ if (gap.unknown.length > 0) {
44
+ return {
45
+ name: 'migrations',
46
+ severity: 'warning',
47
+ summary: `the database is ahead of this CLI by ${gap.unknown.length} migration(s)`,
48
+ details: gap.unknown.map((v) => `${v} is applied but not shipped here — upgrade the CLI`),
49
+ };
50
+ }
51
+ if (gap.pending.length > 0) {
52
+ return {
53
+ name: 'migrations',
54
+ severity: 'problem',
55
+ summary: `${gap.pending.length} migration(s) pending`,
56
+ details: gap.pending.map((m) => m.file),
57
+ };
58
+ }
59
+ return {
60
+ name: 'migrations',
61
+ severity: 'ok',
62
+ summary: `${gap.applied.length} applied, none pending`,
63
+ };
64
+ }
65
+ /**
66
+ * Every object this release defines, against what the database holds.
67
+ *
68
+ * The list is generated from the migrations and ships with the CLI, so the
69
+ * check cannot drift: see `inventory.ts` for why missing, extra and a policy
70
+ * are three different severities.
71
+ *
72
+ * The two schema versions are reported and never gate the comparison. A
73
+ * database older than the CLI is precisely when an operator runs this, and
74
+ * refusing to look would be refusing the case: what it says then is which
75
+ * version the inventory describes, which one the database reports, and what
76
+ * differs between them.
77
+ */
78
+ async function checkCatalogue(db, expected) {
79
+ if (expected === undefined) {
80
+ return {
81
+ name: 'catalogue',
82
+ severity: 'warning',
83
+ summary: 'this build ships no inventory, so there is nothing to compare against',
84
+ details: ['Run `npm run build` in a checkout, or reinstall the package.'],
85
+ };
86
+ }
87
+ const comparison = await compareCatalogue(db, expected);
88
+ const faults = [];
89
+ const information = [];
90
+ for (const section of comparison.sections) {
91
+ const lines = describeDifferences(section);
92
+ faults.push(...lines.faults);
93
+ information.push(...lines.information);
94
+ }
95
+ const versions = comparison.databaseVersion === comparison.expectedVersion
96
+ ? []
97
+ : [
98
+ `the inventory describes schema ${comparison.expectedVersion ?? 'unknown'}, ` +
99
+ `the database reports ${comparison.databaseVersion ?? 'none'} — compared anyway`,
100
+ ];
101
+ const skipped = comparison.sections
102
+ .filter((s) => !s.installed)
103
+ .map((s) => `${s.code} is not installed here, so none of its objects are required`);
104
+ const data = { ...comparison };
105
+ if (faults.length === 0) {
106
+ return {
107
+ name: 'catalogue',
108
+ severity: comparison.extra > 0 ? 'warning' : 'ok',
109
+ summary: comparison.extra > 0
110
+ ? `everything this release defines is there, and ${comparison.extra} object(s) it does not`
111
+ : 'every object this release defines is there, and nothing else',
112
+ details: [...versions, ...skipped, ...cap(information)],
113
+ data,
114
+ };
115
+ }
116
+ return {
117
+ name: 'catalogue',
118
+ severity: 'problem',
119
+ summary: `${comparison.missing} object(s) missing, ${comparison.changed} changed, ` +
120
+ `${comparison.extra} added`,
121
+ details: [...versions, ...skipped, ...cap(faults), ...cap(information)],
122
+ data,
123
+ };
124
+ }
125
+ /** Twenty lines of evidence, then a count. A doctor nobody reads is no doctor. */
126
+ function cap(lines, limit = 20) {
127
+ if (lines.length <= limit)
128
+ return lines;
129
+ return [...lines.slice(0, limit), `… and ${lines.length - limit} more (see --json)`];
130
+ }
131
+ /**
132
+ * The privileges the schema declares against the ones it holds.
133
+ *
134
+ * Row level security decides which rows a role sees; a grant decides whether
135
+ * the statement is allowed to run at all. Both are needed and only one of them
136
+ * used to be written down — until `20260914151207` the grants came from a
137
+ * Supabase project's default privileges, which hand `anon` everything and
138
+ * disappear the day `public` is recreated. This asks a live database whether
139
+ * it still matches the `grants` section of the inventory.
140
+ *
141
+ * Its own check rather than a category of `catalogue`, because the rule is not
142
+ * the same. A missing grant is a problem: it is invisible to every other check
143
+ * and it reaches a user as "permission denied for table companies". An extra
144
+ * grant to `anon` is a problem too — the anonymous role reaches the policy
145
+ * helpers and nothing else, and one more is a surface nobody meant to open. An
146
+ * extra grant to `authenticated` or `service_role` is a warning: often a local
147
+ * customisation, never nothing. A default privilege still standing is a
148
+ * warning wherever it is, because a privilege that comes from there comes from
149
+ * something no migration wrote and a recreated schema takes away.
150
+ */
151
+ async function checkGrants(db, expected) {
152
+ if (expected === undefined) {
153
+ return {
154
+ name: 'grants',
155
+ severity: 'warning',
156
+ summary: 'this CLI ships no inventory, so the privileges cannot be compared',
157
+ details: ['Reinstall the package, or run `npm run inventory` in a checkout.'],
158
+ };
159
+ }
160
+ const findings = [];
161
+ const defaults = [];
162
+ const schemas = [];
163
+ for (const section of await installedSections(db, expected)) {
164
+ // An inventory generated before the grants joined it has no declaration to
165
+ // compare against, and silence is not an assertion.
166
+ if (section.grants === undefined)
167
+ continue;
168
+ schemas.push(section.schema);
169
+ const actual = await readGrants(db, section.schema);
170
+ findings.push(...compareSection(section.grants, actual));
171
+ for (const entry of actual.defaultPrivileges) {
172
+ defaults.push(`${section.schema}: a default privilege still stands (${entry}) — grants should come from a migration`);
173
+ }
174
+ }
175
+ if (schemas.length === 0) {
176
+ return {
177
+ name: 'grants',
178
+ severity: 'warning',
179
+ summary: 'the inventory this CLI ships declares no privileges',
180
+ details: ['It was generated before the schema granted its own rights. Upgrade the CLI.'],
181
+ };
182
+ }
183
+ const problems = findings.filter((f) => f.difference === 'missing' || f.role === 'anon');
184
+ const warnings = findings.filter((f) => !problems.includes(f));
185
+ const data = { problems, warnings, defaultPrivileges: defaults };
186
+ if (problems.length > 0) {
187
+ return {
188
+ name: 'grants',
189
+ severity: 'problem',
190
+ summary: `${problems.length} privilege(s) do not match what this release declares`,
191
+ details: cap([
192
+ ...problems.map(describeFinding),
193
+ ...warnings.map((f) => `${describeFinding(f)} (warning)`),
194
+ ...defaults,
195
+ 'A missing grant answers "permission denied" to the first client and to nothing else.',
196
+ 'Run `ekwo migrate`; if that does not close it, the privileges were changed by hand.',
197
+ ]),
198
+ data,
199
+ };
200
+ }
201
+ if (warnings.length > 0 || defaults.length > 0) {
202
+ return {
203
+ name: 'grants',
204
+ severity: 'warning',
205
+ summary: `${warnings.length + defaults.length} privilege(s) wider than this release declares`,
206
+ details: cap([
207
+ ...warnings.map(describeFinding),
208
+ ...defaults,
209
+ 'Row level security is then the only thing refusing a verb the schema meant to withhold.',
210
+ ]),
211
+ data,
212
+ };
213
+ }
214
+ return {
215
+ name: 'grants',
216
+ severity: 'ok',
217
+ summary: `every privilege in ${schemas.join(', ')} is the one the schema grants itself`,
218
+ };
219
+ }
220
+ async function checkRowLevelSecurity(db) {
221
+ const rows = await db.query(`select c.relname as tablename
222
+ from pg_class c
223
+ join pg_namespace n on n.oid = c.relnamespace
224
+ where n.nspname = 'public' and c.relkind = 'r' and not c.relrowsecurity
225
+ order by c.relname`);
226
+ if (rows.length === 0) {
227
+ return { name: 'row level security', severity: 'ok', summary: 'enabled on every table' };
228
+ }
229
+ return {
230
+ name: 'row level security',
231
+ severity: 'problem',
232
+ summary: `${rows.length} table(s) without row level security`,
233
+ details: rows.map((r) => r.tablename),
234
+ };
235
+ }
236
+ async function checkPolicies(db) {
237
+ const rows = await db.query(`select c.relname as tablename
238
+ from pg_class c
239
+ join pg_namespace n on n.oid = c.relnamespace
240
+ where n.nspname = 'public' and c.relkind = 'r' and c.relrowsecurity
241
+ and not exists (select 1 from pg_policy p where p.polrelid = c.oid)
242
+ order by c.relname`);
243
+ if (rows.length === 0) {
244
+ return { name: 'policies', severity: 'ok', summary: 'every protected table has a policy' };
245
+ }
246
+ return {
247
+ name: 'policies',
248
+ severity: 'problem',
249
+ summary: `${rows.length} table(s) with row level security and no policy — nobody can read them`,
250
+ details: rows.map((r) => r.tablename),
251
+ };
252
+ }
253
+ /**
254
+ * `company_members` deliberately has no foreign key to `auth.users`: inviting
255
+ * someone into a company before they have an account is a normal thing to
256
+ * want. The price is that deleting a user leaves a row behind, and this is
257
+ * where that price is paid.
258
+ */
259
+ async function checkOrphanMembers(db) {
260
+ const rows = await db.query(`select c.name as company, m.user_id
261
+ from company_members m
262
+ join companies c on c.id = m.company_id
263
+ where not exists (select 1 from auth.users u where u.id = m.user_id)
264
+ order by c.name`);
265
+ if (rows.length === 0) {
266
+ return {
267
+ name: 'company members',
268
+ severity: 'ok',
269
+ summary: 'every membership points at a real user',
270
+ };
271
+ }
272
+ return {
273
+ name: 'company members',
274
+ severity: 'warning',
275
+ summary: `${rows.length} membership row(s) whose user no longer exists in Supabase Auth`,
276
+ details: [
277
+ ...rows.map((r) => `${r.company}: ${r.user_id}`),
278
+ 'These grant nothing — auth.uid() can never match them — but they misreport who has access.',
279
+ 'Delete them, or re-invite the person, once you know which it should be.',
280
+ ],
281
+ };
282
+ }
283
+ async function checkOrphanAdmins(db) {
284
+ const rows = await db.query(`select a.user_id from instance_admins a
285
+ where not exists (select 1 from auth.users u where u.id = a.user_id)`);
286
+ if (rows.length === 0) {
287
+ const count = await scalar(db, 'select count(*)::text from instance_admins');
288
+ return {
289
+ name: 'instance administrators',
290
+ severity: count === '0' ? 'warning' : 'ok',
291
+ summary: count === '0'
292
+ ? 'no administrator: nobody can create a company here'
293
+ : `${count ?? '0'} administrator(s), all real users`,
294
+ };
295
+ }
296
+ return {
297
+ name: 'instance administrators',
298
+ severity: 'problem',
299
+ summary: `${rows.length} administrator(s) whose user no longer exists`,
300
+ details: [
301
+ ...rows.map((r) => r.user_id),
302
+ 'The foreign key to auth.users should have cascaded these away. Check that it is still there.',
303
+ ],
304
+ };
305
+ }
306
+ /**
307
+ * A company with no bank account has nowhere for a payment to land.
308
+ *
309
+ * `post_payment` resolves the money side from the payment's bank account, or
310
+ * from the default account of its journal — and the country template wires
311
+ * that second one, so this is never an error. It is the configuration an
312
+ * operator meant to finish and did not: without a bank account there is no
313
+ * IBAN on an invoice, no statement to import and nothing to reconcile
314
+ * against. So: a warning, naming the companies and the command that fixes it.
315
+ */
316
+ async function checkBankAccounts(db) {
317
+ const rows = await db.query(`select c.name
318
+ from companies c
319
+ where not exists (
320
+ select 1 from bank_accounts b where b.company_id = c.id and b.active
321
+ )
322
+ order by c.name`);
323
+ if (rows.length === 0) {
324
+ const count = await scalar(db, 'select count(*)::text from companies');
325
+ return {
326
+ name: 'bank accounts',
327
+ severity: 'ok',
328
+ summary: count === '0'
329
+ ? 'no company yet, so nothing to bank'
330
+ : 'every company has at least one bank account',
331
+ };
332
+ }
333
+ return {
334
+ name: 'bank accounts',
335
+ severity: 'warning',
336
+ summary: `${rows.length} company/companies with no bank account`,
337
+ details: [
338
+ ...rows.map((r) => r.name),
339
+ 'Payments still book — the bank journal carries a default account — but there is no IBAN to',
340
+ 'put on an invoice and no statement to reconcile against.',
341
+ 'Add one with `ekwo init --iban …` on the same project, or the create_bank_account tool of the MCP server.',
342
+ ],
343
+ };
344
+ }
345
+ async function checkStatements(db) {
346
+ const rows = await db.query(`select c.name as company, s.statement_date::text,
347
+ s.balance_end_declared::text as declared,
348
+ s.balance_end_computed::text as computed
349
+ from bank_statements s
350
+ join companies c on c.id = s.company_id
351
+ where not s.is_consistent
352
+ order by s.statement_date`);
353
+ if (rows.length === 0) {
354
+ return {
355
+ name: 'bank statements',
356
+ severity: 'ok',
357
+ summary: 'every statement ties to its lines',
358
+ };
359
+ }
360
+ return {
361
+ name: 'bank statements',
362
+ severity: 'warning',
363
+ summary: `${rows.length} statement(s) whose closing balance does not match their lines`,
364
+ details: rows.map((r) => `${r.company} ${r.statement_date}: declared ${r.declared}, lines give ${r.computed}`),
365
+ };
366
+ }
367
+ async function checkPostedEntriesBalance(db) {
368
+ const rows = await db.query(`select e.number, e.entry_date::text
369
+ from entries e
370
+ where e.state = 'posted' and not e.is_balanced
371
+ order by e.entry_date`);
372
+ if (rows.length === 0) {
373
+ return { name: 'posted entries', severity: 'ok', summary: 'every posted entry balances' };
374
+ }
375
+ return {
376
+ name: 'posted entries',
377
+ severity: 'problem',
378
+ summary: `${rows.length} posted entry/entries do not balance`,
379
+ details: rows.map((r) => `${r.number ?? '(no number)'} on ${r.entry_date}`),
380
+ };
381
+ }
382
+ /**
383
+ * The audit trail still being what it claims to be.
384
+ *
385
+ * Everything here is read from the catalogue rather than from a list kept by
386
+ * hand: the trail is append-only, so the guard trigger has to be on the table
387
+ * and no policy may let a client write, update or delete a row. A migration
388
+ * added later that put an insert policy on `audit_log` "so the application can
389
+ * log too" would break the one property the table exists for, and nothing else
390
+ * would notice.
391
+ */
392
+ async function checkAuditTrail(db) {
393
+ const installed = (await scalar(db, `select exists (
394
+ select 1 from information_schema.tables
395
+ where table_schema = 'public' and table_name = 'audit_log'
396
+ )`)) === true;
397
+ if (!installed) {
398
+ return {
399
+ name: 'audit trail',
400
+ severity: 'problem',
401
+ summary: 'audit_log is not there',
402
+ details: ['The migration that creates it has not been applied. Run `ekwo migrate`.'],
403
+ };
404
+ }
405
+ const faults = [];
406
+ const guarded = await db.query(`select t.tgname from pg_trigger t
407
+ join pg_class c on c.oid = t.tgrelid
408
+ where c.relname = 'audit_log' and not t.tgisinternal`);
409
+ if (guarded.length === 0) {
410
+ faults.push('no trigger on audit_log: nothing refuses an update or a delete on it any more');
411
+ }
412
+ const rls = (await scalar(db, `select relrowsecurity from pg_class where relname = 'audit_log' and relnamespace = 'public'::regnamespace`)) === true;
413
+ if (!rls)
414
+ faults.push('row level security is off on audit_log: every signed-in user reads every company');
415
+ const writable = await db.query(`select p.polname, case p.polcmd
416
+ when 'a' then 'insert' when 'w' then 'update'
417
+ when 'd' then 'delete' when '*' then 'all' else 'select' end as cmd
418
+ from pg_policy p
419
+ join pg_class c on c.oid = p.polrelid
420
+ where c.relname = 'audit_log' and p.polcmd <> 'r'`);
421
+ for (const policy of writable) {
422
+ faults.push(`policy ${policy.polname} allows ${policy.cmd} on audit_log, which is append-only`);
423
+ }
424
+ const purgers = await db.query(`select a.grantee from (
425
+ select (aclexplode(p.proacl)).grantee as grantee
426
+ from pg_proc p
427
+ where p.proname = 'purge_audit_log'
428
+ ) a
429
+ where a.grantee <> 0 and pg_get_userbyid(a.grantee) not in ('service_role', current_user)`);
430
+ for (const grant of purgers) {
431
+ faults.push(`purge_audit_log is executable by a role other than service_role (${grant.grantee})`);
432
+ }
433
+ if (faults.length === 0) {
434
+ const rows = await scalar(db, 'select count(*)::text from audit_log');
435
+ return {
436
+ name: 'audit trail',
437
+ severity: 'ok',
438
+ summary: `append-only, ${rows ?? '0'} row(s) recorded`,
439
+ };
440
+ }
441
+ return {
442
+ name: 'audit trail',
443
+ severity: 'problem',
444
+ summary: `${faults.length} thing(s) the audit trail no longer guarantees`,
445
+ details: faults,
446
+ };
447
+ }
448
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The privileges the schema declares, and how a live database is compared to
3
+ * them.
4
+ *
5
+ * Since `20260914151207` every table, view and function of Ekwo names the
6
+ * roles that may reach it, in the migration that creates it. Before that the
7
+ * privileges came from a Supabase project's default privileges on `public`,
8
+ * which gave `anon` — the role behind the publishable key — `all` on every
9
+ * table of the ledger, and which vanish the day somebody recreates the schema.
10
+ *
11
+ * The declaration travels in `packages/cli/assets/expected-objects.json`,
12
+ * under `grants` in each schema's section: the same inventory that carries the
13
+ * tables, the policies and the triggers a release defines, generated by
14
+ * `scripts/generate-expected-objects.mjs` from a freshly migrated database and
15
+ * committed. One file, because the privileges of an object and the object are
16
+ * the same release. This module reads the same catalogue out of a live
17
+ * installation and says where the two differ:
18
+ *
19
+ * - a **missing** grant is a problem. It is the failure PostgREST reports as
20
+ * "permission denied for table companies" to the first user, and it passes
21
+ * every other check there is.
22
+ * - an **extra** grant to `anon` is a problem. The anonymous role reaches
23
+ * the policy helpers and nothing else; anything more is a surface somebody
24
+ * opened by hand or a default privilege that was never taken away.
25
+ * - an **extra** grant to `authenticated` or `service_role` is a warning. It
26
+ * is usually a local customisation and it is never nothing: row level
27
+ * security is then the only thing refusing a verb the schema meant to
28
+ * withhold.
29
+ *
30
+ * The SQL that describes a schema lives here rather than in the generator, so
31
+ * that the file and the check can never read the catalogue two different ways.
32
+ * `inventory.ts` calls `describeGrants` to fill the section, and `doctor.ts`
33
+ * calls it again on the live database and hands both to `compareSection`.
34
+ */
35
+ /** The three roles a Supabase project exposes to a client. */
36
+ export declare const GRANT_ROLES: readonly ["anon", "authenticated", "service_role"];
37
+ export type GrantRole = (typeof GRANT_ROLES)[number];
38
+ /** Privileges held on one object, by role. Lower case, sorted. */
39
+ export type HeldBy = Record<GrantRole, string[]>;
40
+ export interface GrantedObject extends HeldBy {
41
+ name: string;
42
+ /** Functions only: the identity arguments that tell an overload apart. */
43
+ arguments?: string;
44
+ /** Functions only, and true when the function returns `trigger`. */
45
+ trigger?: boolean;
46
+ }
47
+ export interface GrantsSection extends Record<string, unknown> {
48
+ schema: string;
49
+ /** `usage` on the schema itself, which is what makes the rest reachable. */
50
+ usage: HeldBy;
51
+ tables: GrantedObject[];
52
+ views: GrantedObject[];
53
+ sequences: GrantedObject[];
54
+ functions: GrantedObject[];
55
+ /**
56
+ * Default privileges still standing on the schema, as
57
+ * `owner:objtype:role:privilege`. Empty is the point: a privilege that comes
58
+ * from here comes from something no migration wrote.
59
+ */
60
+ defaultPrivileges: string[];
61
+ }
62
+ /** Rows from one parameterised query. Both PGlite and the CLI client fit. */
63
+ export type QueryRows = <T>(sql: string, params: unknown[]) => Promise<T[]>;
64
+ /**
65
+ * Every privilege one schema hands to the three roles, object by object.
66
+ *
67
+ * `aclexplode` turns an `aclitem[]` into one row per grantee and privilege,
68
+ * which is the only shape worth comparing: the text form of an ACL depends on
69
+ * the owner's name and on the order the privileges happen to sit in. The
70
+ * owner's own grants are dropped — they are not a declaration, they are what
71
+ * owning a table means.
72
+ */
73
+ export declare function describeGrants(rows: QueryRows, schema: string): Promise<GrantsSection>;
74
+ export type Difference = 'missing' | 'extra';
75
+ export interface GrantFinding {
76
+ schema: string;
77
+ /** `table entries`, `function post_entry(p_entry_id uuid)`. */
78
+ object: string;
79
+ role: GrantRole;
80
+ difference: Difference;
81
+ /** The privileges that are missing, or the ones that are too many. */
82
+ privileges: string[];
83
+ }
84
+ /** Every difference between what a schema declares and what it holds. */
85
+ export declare function compareSection(expected: GrantsSection, actual: GrantsSection): GrantFinding[];
86
+ /** A finding as one line of the doctor's output. */
87
+ export declare function describeFinding(finding: GrantFinding): string;
88
+ //# sourceMappingURL=grants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,WAAW,oDAAqD,CAAC;AAC9E,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,kEAAkE;AAClE,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,aAAc,SAAQ,MAAM;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,6EAA6E;AAC7E,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;AAI5E;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiG5F;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,sEAAsE;IACtE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AA2BD,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG,YAAY,EAAE,CAgC7F;AAED,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAG7D"}