celerp 2.3.4__tar.gz → 2.3.5__tar.gz

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 (662) hide show
  1. {celerp-2.3.4 → celerp-2.3.5}/PKG-INFO +1 -1
  2. celerp-2.3.5/celerp/capacity.py +22 -0
  3. {celerp-2.3.4 → celerp-2.3.5}/celerp/db.py +10 -7
  4. {celerp-2.3.4 → celerp-2.3.5}/celerp/main.py +2 -0
  5. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/loader.py +232 -9
  6. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/slots.py +27 -8
  7. {celerp-2.3.4 → celerp-2.3.5}/celerp/projections/engine.py +8 -5
  8. celerp-2.3.5/celerp/routers/search.py +305 -0
  9. {celerp-2.3.4 → celerp-2.3.5}/celerp.egg-info/PKG-INFO +1 -1
  10. {celerp-2.3.4 → celerp-2.3.5}/celerp.egg-info/SOURCES.txt +8 -0
  11. {celerp-2.3.4 → celerp-2.3.5}/celerp.egg-info/scm_file_list.json +18 -0
  12. celerp-2.3.5/celerp.egg-info/scm_version.json +8 -0
  13. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/__init__.py +5 -0
  14. celerp-2.3.5/default_modules/celerp-accounting/celerp_accounting/search.py +30 -0
  15. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/__init__.py +5 -0
  16. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/celerp_contacts/routes.py +6 -24
  17. celerp-2.3.5/default_modules/celerp-contacts/celerp_contacts/search.py +75 -0
  18. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/__init__.py +5 -0
  19. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/routes.py +4 -15
  20. celerp-2.3.5/default_modules/celerp-docs/celerp_docs/search.py +68 -0
  21. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/__init__.py +5 -0
  22. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/routes.py +76 -103
  23. celerp-2.3.5/default_modules/celerp-inventory/celerp_inventory/search.py +265 -0
  24. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/__init__.py +5 -0
  25. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/routes.py +3 -31
  26. celerp-2.3.5/default_modules/celerp-manufacturing/celerp_manufacturing/search.py +74 -0
  27. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-subscriptions/__init__.py +5 -0
  28. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-subscriptions/celerp_subscriptions/routes.py +4 -41
  29. celerp-2.3.5/default_modules/celerp-subscriptions/celerp_subscriptions/search.py +85 -0
  30. {celerp-2.3.4 → celerp-2.3.5}/default_modules/first_party.lock.json +6 -6
  31. {celerp-2.3.4 → celerp-2.3.5}/ui/api_client.py +631 -159
  32. {celerp-2.3.4 → celerp-2.3.5}/ui/app.py +9 -9
  33. {celerp-2.3.4 → celerp-2.3.5}/ui/components/shell.py +63 -18
  34. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/am.json +3 -0
  35. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/ar.json +3 -0
  36. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/de.json +3 -0
  37. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/en.json +3 -0
  38. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/es.json +3 -0
  39. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/fr.json +3 -0
  40. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/id.json +3 -0
  41. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/it.json +3 -0
  42. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/ja.json +3 -0
  43. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/pt.json +3 -0
  44. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/th.json +3 -0
  45. {celerp-2.3.4 → celerp-2.3.5}/ui/locales/vi.json +3 -0
  46. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/auth.py +8 -15
  47. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/inventory.py +173 -77
  48. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/notifications.py +7 -19
  49. celerp-2.3.5/ui/routes/search.py +218 -0
  50. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings.py +12 -25
  51. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/stars.py +11 -16
  52. celerp-2.3.5/ui/security.py +44 -0
  53. celerp-2.3.4/celerp.egg-info/scm_version.json +0 -8
  54. celerp-2.3.4/ui/routes/search.py +0 -170
  55. celerp-2.3.4/ui/security.py +0 -19
  56. {celerp-2.3.4 → celerp-2.3.5}/CLA.md +0 -0
  57. {celerp-2.3.4 → celerp-2.3.5}/CONTRIBUTING.md +0 -0
  58. {celerp-2.3.4 → celerp-2.3.5}/LICENSE +0 -0
  59. {celerp-2.3.4 → celerp-2.3.5}/LICENSING.md +0 -0
  60. {celerp-2.3.4 → celerp-2.3.5}/MANIFEST.in +0 -0
  61. {celerp-2.3.4 → celerp-2.3.5}/NOTICE +0 -0
  62. {celerp-2.3.4 → celerp-2.3.5}/README.md +0 -0
  63. {celerp-2.3.4 → celerp-2.3.5}/alembic.ini +0 -0
  64. {celerp-2.3.4 → celerp-2.3.5}/celerp/__init__.py +0 -0
  65. {celerp-2.3.4 → celerp-2.3.5}/celerp/__main__.py +0 -0
  66. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/__init__.py +0 -0
  67. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/batch.py +0 -0
  68. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/cleanup.py +0 -0
  69. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/commands.py +0 -0
  70. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/conversations.py +0 -0
  71. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/files.py +0 -0
  72. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/intent.py +0 -0
  73. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/llm.py +0 -0
  74. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/memory.py +0 -0
  75. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/models.py +0 -0
  76. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/page_count.py +0 -0
  77. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/quota.py +0 -0
  78. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/service.py +0 -0
  79. {celerp-2.3.4 → celerp-2.3.5}/celerp/ai/tools.py +0 -0
  80. {celerp-2.3.4 → celerp-2.3.5}/celerp/alembic.ini +0 -0
  81. {celerp-2.3.4 → celerp-2.3.5}/celerp/alembic_config.py +0 -0
  82. {celerp-2.3.4 → celerp-2.3.5}/celerp/cli.py +0 -0
  83. {celerp-2.3.4 → celerp-2.3.5}/celerp/compat.py +0 -0
  84. {celerp-2.3.4 → celerp-2.3.5}/celerp/compute/__init__.py +0 -0
  85. {celerp-2.3.4 → celerp-2.3.5}/celerp/compute/aggregations.py +0 -0
  86. {celerp-2.3.4 → celerp-2.3.5}/celerp/compute/valuation.py +0 -0
  87. {celerp-2.3.4 → celerp-2.3.5}/celerp/config.py +0 -0
  88. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/__init__.py +0 -0
  89. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/base.py +0 -0
  90. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/daily_scheduler.py +0 -0
  91. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/http.py +0 -0
  92. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/images.py +0 -0
  93. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/quickbooks.py +0 -0
  94. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/registry.py +0 -0
  95. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/relay_token.py +0 -0
  96. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/shopify.py +0 -0
  97. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/sync_runner.py +0 -0
  98. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/upsert.py +0 -0
  99. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/util.py +0 -0
  100. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/webhooks.py +0 -0
  101. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/woocommerce.py +0 -0
  102. {celerp-2.3.4 → celerp-2.3.5}/celerp/connectors/xero.py +0 -0
  103. {celerp-2.3.4 → celerp-2.3.5}/celerp/constants.py +0 -0
  104. {celerp-2.3.4 → celerp-2.3.5}/celerp/embedded_pg.py +0 -0
  105. {celerp-2.3.4 → celerp-2.3.5}/celerp/events/__init__.py +0 -0
  106. {celerp-2.3.4 → celerp-2.3.5}/celerp/events/engine.py +0 -0
  107. {celerp-2.3.4 → celerp-2.3.5}/celerp/events/schemas.py +0 -0
  108. {celerp-2.3.4 → celerp-2.3.5}/celerp/events/types.py +0 -0
  109. {celerp-2.3.4 → celerp-2.3.5}/celerp/gateway/__init__.py +0 -0
  110. {celerp-2.3.4 → celerp-2.3.5}/celerp/gateway/client.py +0 -0
  111. {celerp-2.3.4 → celerp-2.3.5}/celerp/gateway/state.py +0 -0
  112. {celerp-2.3.4 → celerp-2.3.5}/celerp/importers/__init__.py +0 -0
  113. {celerp-2.3.4 → celerp-2.3.5}/celerp/importers/importer.py +0 -0
  114. {celerp-2.3.4 → celerp-2.3.5}/celerp/importers/schema.py +0 -0
  115. {celerp-2.3.4 → celerp-2.3.5}/celerp/inventory_codes.py +0 -0
  116. {celerp-2.3.4 → celerp-2.3.5}/celerp/middleware.py +0 -0
  117. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/README.md +0 -0
  118. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/_auto_stamp.py +0 -0
  119. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/_data_reconcile.py +0 -0
  120. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/_json_compat.py +0 -0
  121. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/env.py +0 -0
  122. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/script.py.mako +0 -0
  123. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/a0b1c2d3e4f5_seed_landed_cost_clearing_accounts.py +0 -0
  124. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/a1b2c3d4e5f6_add_doc_share_tokens.py +0 -0
  125. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/b1c2d3e4f5a6_add_supporter_badges.py +0 -0
  126. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/b2c3d4e5f6a7_add_import_batches.py +0 -0
  127. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/b3c4d5e6f7a8_expand_role_permissions_to_role_grants.py +0 -0
  128. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/bc0d1e2f3a4b_barcode_unique_index.py +0 -0
  129. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/c1d2e3f4a5b6_add_marketplace.py +0 -0
  130. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/c2d3e4f5a6b7_add_is_sync_to_shopify.py +0 -0
  131. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/c4d5e6f7a8b9_account_cash_flow_category.py +0 -0
  132. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/c9d8e7f6a5b4_seed_shrinkage_writeoff_account.py +0 -0
  133. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/d0e1f2a3b4c5_add_share_token_expiry.py +0 -0
  134. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/d2e3f4a5b6c7_add_password_reset_token.py +0 -0
  135. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/d5e6f7a8b9c0_rename_fx_rounding_to_fx_difference.py +0 -0
  136. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/e3f4a5b6c7d8_add_company_is_active.py +0 -0
  137. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/e4f5a6b7c8d9_backfill_connector_idempotency_key.py +0 -0
  138. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/e7c9a1b3d5f2_work_center_default_columns.py +0 -0
  139. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/f1a2b3c4d5e6_move_accounts_marketplace_to_modules.py +0 -0
  140. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/f6a7b8c9d0e1_seed_fx_rounding_account.py +0 -0
  141. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/f8a9b0c1d2e3_work_center_default_backfill.py +0 -0
  142. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/fd5de461e14e_initial_schema.py +0 -0
  143. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/g1h2i3j4k5l6_add_consignment_flag.py +0 -0
  144. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/h2i3j4k5l6m7_add_bank_accounts_and_reconciliation.py +0 -0
  145. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/j4k5l6m7n8o9_labels_db_persistence.py +0 -0
  146. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/k5l6m7n8o9p0_add_reconciliation_v2.py +0 -0
  147. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/l6m7n8o9p0q1_add_sync_runs_table.py +0 -0
  148. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/m7n8o9p0q1r2_add_connector_configs_and_outbound_queue.py +0 -0
  149. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/n8o9p0q1r2s3_backfill_payment_date.py +0 -0
  150. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/o9p0q1r2s3t4_backfill_item_price_fields.py +0 -0
  151. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/p1q2r3s4t5u6_add_session_registry_and_user_auth_state.py +0 -0
  152. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/q2r3s4t5u6v7_add_system_runtime_state.py +0 -0
  153. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/r3s4t5u6v7w8_add_projections_company_entity_type_index.py +0 -0
  154. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/s4t5u6v7w8x9_drop_user_company_id_role.py +0 -0
  155. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/t5u6v7w8x9y0_seed_inventory_sub_accounts.py +0 -0
  156. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/u6v7w8x9y0z1_backfill_item_prices_from_attributes.py +0 -0
  157. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/v7w8x9y0z1a2_backfill_purchase_unit_defaults.py +0 -0
  158. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/w8x9y0z1a2b3_backfill_category_unit_defaults.py +0 -0
  159. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/x7y8z9a0b1c2_add_projection_created_at.py +0 -0
  160. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/y8z9a0b1c2d3_per_company_ledger_idempotency.py +0 -0
  161. {celerp-2.3.4 → celerp-2.3.5}/celerp/migrations/versions/z9a0b1c2d3e4_work_centers.py +0 -0
  162. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/__init__.py +0 -0
  163. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/accounting.py +0 -0
  164. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/ai.py +0 -0
  165. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/auth.py +0 -0
  166. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/base.py +0 -0
  167. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/company.py +0 -0
  168. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/connector_config.py +0 -0
  169. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/import_batch.py +0 -0
  170. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/ledger.py +0 -0
  171. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/marketplace.py +0 -0
  172. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/notification.py +0 -0
  173. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/projections.py +0 -0
  174. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/share.py +0 -0
  175. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/supporter.py +0 -0
  176. {celerp-2.3.4 → celerp-2.3.5}/celerp/models/sync_run.py +0 -0
  177. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/__init__.py +0 -0
  178. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/api.py +0 -0
  179. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/audit.py +0 -0
  180. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/demotion.py +0 -0
  181. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/importer.py +0 -0
  182. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/license.py +0 -0
  183. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/meta.py +0 -0
  184. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/migrations_runner.py +0 -0
  185. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/references.py +0 -0
  186. {celerp-2.3.4 → celerp-2.3.5}/celerp/modules/registry.py +0 -0
  187. {celerp-2.3.4 → celerp-2.3.5}/celerp/notifications/__init__.py +0 -0
  188. {celerp-2.3.4 → celerp-2.3.5}/celerp/notifications/service.py +0 -0
  189. {celerp-2.3.4 → celerp-2.3.5}/celerp/notifications/sse.py +0 -0
  190. {celerp-2.3.4 → celerp-2.3.5}/celerp/output/__init__.py +0 -0
  191. {celerp-2.3.4 → celerp-2.3.5}/celerp/output/branding.py +0 -0
  192. {celerp-2.3.4 → celerp-2.3.5}/celerp/output/doc_print.py +0 -0
  193. {celerp-2.3.4 → celerp-2.3.5}/celerp/output/pdf.py +0 -0
  194. {celerp-2.3.4 → celerp-2.3.5}/celerp/output/share_render.py +0 -0
  195. {celerp-2.3.4 → celerp-2.3.5}/celerp/projections/__init__.py +0 -0
  196. {celerp-2.3.4 → celerp-2.3.5}/celerp/projections/handlers/__init__.py +0 -0
  197. {celerp-2.3.4 → celerp-2.3.5}/celerp/projections/handlers/marketplace.py +0 -0
  198. {celerp-2.3.4 → celerp-2.3.5}/celerp/projections/handlers/scanning.py +0 -0
  199. {celerp-2.3.4 → celerp-2.3.5}/celerp/projections/handlers/shopify.py +0 -0
  200. {celerp-2.3.4 → celerp-2.3.5}/celerp/projections/handlers/system.py +0 -0
  201. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/__init__.py +0 -0
  202. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/auth.py +0 -0
  203. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/companies.py +0 -0
  204. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/debug.py +0 -0
  205. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/doctor.py +0 -0
  206. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/events.py +0 -0
  207. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/health.py +0 -0
  208. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/ledger.py +0 -0
  209. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/notifications.py +0 -0
  210. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/stars.py +0 -0
  211. {celerp-2.3.4 → celerp-2.3.5}/celerp/routers/system.py +0 -0
  212. {celerp-2.3.4 → celerp-2.3.5}/celerp/schemas/__init__.py +0 -0
  213. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/__init__.py +0 -0
  214. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/activity_redaction.py +0 -0
  215. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/attachments.py +0 -0
  216. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/auth.py +0 -0
  217. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/auto_je.py +0 -0
  218. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/backup.py +0 -0
  219. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/backup_export.py +0 -0
  220. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/backup_import.py +0 -0
  221. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/backup_repo.py +0 -0
  222. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/backup_scheduler.py +0 -0
  223. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/backup_state.py +0 -0
  224. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/cogs_backfill.py +0 -0
  225. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/cost_visibility.py +0 -0
  226. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/demo.py +0 -0
  227. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/dev_release_guard.py +0 -0
  228. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/email.py +0 -0
  229. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/field_schema.py +0 -0
  230. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/fulfill.py +0 -0
  231. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/holdings.py +0 -0
  232. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/je_keys.py +0 -0
  233. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/landed_cost.py +0 -0
  234. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/line_measures.py +0 -0
  235. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/list_behavior.py +0 -0
  236. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/money.py +0 -0
  237. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/payments.py +0 -0
  238. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/permissions.py +0 -0
  239. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/pick.py +0 -0
  240. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/pricing.py +0 -0
  241. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/relay_share.py +0 -0
  242. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/reorder.py +0 -0
  243. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/runtime_state.py +0 -0
  244. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/session_tracker.py +0 -0
  245. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/shipping.py +0 -0
  246. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/star_cta.py +0 -0
  247. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/status_doc_backfill.py +0 -0
  248. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/supporter_badge.py +0 -0
  249. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/system_health.py +0 -0
  250. {celerp-2.3.4 → celerp-2.3.5}/celerp/services/units.py +0 -0
  251. {celerp-2.3.4 → celerp-2.3.5}/celerp/session_gate.py +0 -0
  252. {celerp-2.3.4 → celerp-2.3.5}/celerp/tax_regimes.py +0 -0
  253. {celerp-2.3.4 → celerp-2.3.5}/celerp.egg-info/dependency_links.txt +0 -0
  254. {celerp-2.3.4 → celerp-2.3.5}/celerp.egg-info/entry_points.txt +0 -0
  255. {celerp-2.3.4 → celerp-2.3.5}/celerp.egg-info/requires.txt +0 -0
  256. {celerp-2.3.4 → celerp-2.3.5}/celerp.egg-info/top_level.txt +0 -0
  257. {celerp-2.3.4 → celerp-2.3.5}/conftest.py +0 -0
  258. {celerp-2.3.4 → celerp-2.3.5}/conftest_support.py +0 -0
  259. {celerp-2.3.4 → celerp-2.3.5}/default_modules/__init__.py +0 -0
  260. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/LICENSE +0 -0
  261. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/__init__.py +0 -0
  262. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/api_setup.py +0 -0
  263. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/csv_parser.py +0 -0
  264. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/matcher.py +0 -0
  265. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/models.py +0 -0
  266. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/projections.py +0 -0
  267. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/routes.py +0 -0
  268. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/celerp_accounting/ui_routes.py +0 -0
  269. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/balance-sheet.html +0 -0
  270. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/cash-flow.html +0 -0
  271. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-csv.csv +0 -0
  272. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-print.html +0 -0
  273. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/extended-journal.html +0 -0
  274. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/general-ledger.html +0 -0
  275. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/journal-csv.csv +0 -0
  276. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/journal-print.html +0 -0
  277. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/journal.html +0 -0
  278. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/ledger.html +0 -0
  279. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/pnl.html +0 -0
  280. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/statement.html +0 -0
  281. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/report_goldens/trial-balance.html +0 -0
  282. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_accounting_banking.py +0 -0
  283. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_accounting_banking_routers.py +0 -0
  284. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_accounting_gaps.py +0 -0
  285. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_accounting_import_idempotency.py +0 -0
  286. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_cash_flow.py +0 -0
  287. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_financial_reports_ui.py +0 -0
  288. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_journal_gl_soa.py +0 -0
  289. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_journal_gl_soa_ui.py +0 -0
  290. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_reconciliation_v2.py +0 -0
  291. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_reports_end_to_end.py +0 -0
  292. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-accounting/tests/test_route_permissions.py +0 -0
  293. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-admin/__init__.py +0 -0
  294. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-admin/celerp_admin/__init__.py +0 -0
  295. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-admin/celerp_admin/routes.py +0 -0
  296. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-admin/celerp_admin/setup.py +0 -0
  297. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/__init__.py +0 -0
  298. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/celerp_ai/__init__.py +0 -0
  299. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/celerp_ai/routes.py +0 -0
  300. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/celerp_ai/setup.py +0 -0
  301. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/celerp_ai/ui_routes.py +0 -0
  302. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/conftest.py +0 -0
  303. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_batch.py +0 -0
  304. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_cleanup.py +0 -0
  305. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_conversations.py +0 -0
  306. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_coverage_gaps.py +0 -0
  307. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_intent.py +0 -0
  308. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_llm.py +0 -0
  309. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_memory.py +0 -0
  310. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_models.py +0 -0
  311. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_page_count.py +0 -0
  312. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_quota.py +0 -0
  313. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_router.py +0 -0
  314. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_routes_coverage.py +0 -0
  315. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_service.py +0 -0
  316. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-ai/tests/test_tools.py +0 -0
  317. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-backup/__init__.py +0 -0
  318. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-backup/celerp_backup/__init__.py +0 -0
  319. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-backup/celerp_backup/routes.py +0 -0
  320. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-backup/celerp_backup/setup.py +0 -0
  321. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/__init__.py +0 -0
  322. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/celerp_connectors/__init__.py +0 -0
  323. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/celerp_connectors/models.py +0 -0
  324. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/celerp_connectors/routes.py +0 -0
  325. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/__init__.py +0 -0
  326. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/conftest.py +0 -0
  327. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_compliance.py +0 -0
  328. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_connector_correctness.py +0 -0
  329. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_connectors.py +0 -0
  330. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_credentials_routes.py +0 -0
  331. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_images.py +0 -0
  332. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_outbound.py +0 -0
  333. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_quickbooks.py +0 -0
  334. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_rate_limiting.py +0 -0
  335. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_shopify.py +0 -0
  336. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_wiring.py +0 -0
  337. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_woocommerce.py +0 -0
  338. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_woocommerce_webhooks.py +0 -0
  339. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-connectors/tests/test_xero.py +0 -0
  340. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/LICENSE +0 -0
  341. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/celerp_contacts/__init__.py +0 -0
  342. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/celerp_contacts/migrations.py +0 -0
  343. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/celerp_contacts/projections.py +0 -0
  344. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/celerp_contacts/services.py +0 -0
  345. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-contacts/celerp_contacts/ui_routes.py +0 -0
  346. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-dashboard/LICENSE +0 -0
  347. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-dashboard/__init__.py +0 -0
  348. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-dashboard/celerp_dashboard/__init__.py +0 -0
  349. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-dashboard/celerp_dashboard/routes.py +0 -0
  350. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-dashboard/celerp_dashboard/setup.py +0 -0
  351. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/LICENSE +0 -0
  352. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/__init__.py +0 -0
  353. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/api_setup.py +0 -0
  354. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/doc_constants.py +0 -0
  355. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/doc_email.py +0 -0
  356. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/doc_projections.py +0 -0
  357. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/doc_service.py +0 -0
  358. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/models_share.py +0 -0
  359. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/routes_payments.py +0 -0
  360. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/routes_share.py +0 -0
  361. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/sequences.py +0 -0
  362. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/taxes.py +0 -0
  363. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/celerp_docs/ui_routes.py +0 -0
  364. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/conftest.py +0 -0
  365. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_audits.py +0 -0
  366. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_bulk_payment_alloc_lock.py +0 -0
  367. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_consolidate_lots.py +0 -0
  368. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_cross_lot_settlement.py +0 -0
  369. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_freight_je.py +0 -0
  370. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_freight_lines.py +0 -0
  371. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_fulfill_no_split.py +0 -0
  372. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_fulfillment_activity.py +0 -0
  373. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_inbound_je_lifecycle.py +0 -0
  374. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_inventory_account_reconciliation.py +0 -0
  375. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_landed_receive.py +0 -0
  376. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_line_delete_persist.py +0 -0
  377. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_line_identifier.py +0 -0
  378. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_line_page_patch_truncate.py +0 -0
  379. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_list_concurrency.py +0 -0
  380. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_list_outcome_concurrency.py +0 -0
  381. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_list_page_no_full_state.py +0 -0
  382. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_list_query_pushdown.py +0 -0
  383. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_memo_close.py +0 -0
  384. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_memo_close_projection.py +0 -0
  385. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_memo_close_review_fixes.py +0 -0
  386. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_memo_lifecycle_concurrency.py +0 -0
  387. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_memo_line_labels.py +0 -0
  388. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_memo_unfulfilled_filter.py +0 -0
  389. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_payment_void_activity.py +0 -0
  390. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_receive_sku_batch.py +0 -0
  391. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_send_visibility.py +0 -0
  392. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_service_lines.py +0 -0
  393. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_sold_label_ordering.py +0 -0
  394. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_void_guards.py +0 -0
  395. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-docs/tests/test_writeoffs.py +0 -0
  396. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/LICENSE +0 -0
  397. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/__init__.py +0 -0
  398. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/models_import_batch.py +0 -0
  399. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/projections.py +0 -0
  400. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/routes_attachments.py +0 -0
  401. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/routes_scanning.py +0 -0
  402. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/services.py +0 -0
  403. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/celerp_inventory/ui_routes.py +0 -0
  404. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/tests/test_item_recipe_projection.py +0 -0
  405. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/tests/test_item_workflow_projection.py +0 -0
  406. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-inventory/tests/test_landed_cost_projection.py +0 -0
  407. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/LICENSE +0 -0
  408. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/__init__.py +0 -0
  409. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/__init__.py +0 -0
  410. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/am.json +0 -0
  411. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/ar.json +0 -0
  412. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/de.json +0 -0
  413. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/en.json +0 -0
  414. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/es.json +0 -0
  415. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/fr.json +0 -0
  416. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/id.json +0 -0
  417. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/it.json +0 -0
  418. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/ja.json +0 -0
  419. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/pt.json +0 -0
  420. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/th.json +0 -0
  421. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/locales/vi.json +0 -0
  422. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/models.py +0 -0
  423. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/presets.py +0 -0
  424. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/routes.py +0 -0
  425. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/service.py +0 -0
  426. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/celerp_labels/ui_routes.py +0 -0
  427. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/requirements.txt +0 -0
  428. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/tests/test_labels.py +0 -0
  429. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-labels/tests/test_labels_module.py +0 -0
  430. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/LICENSE +0 -0
  431. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/__init__.py +0 -0
  432. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/costing.py +0 -0
  433. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/expansion.py +0 -0
  434. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/labor.py +0 -0
  435. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/migrations.py +0 -0
  436. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/projection_handler.py +0 -0
  437. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/celerp_manufacturing/ui_routes.py +0 -0
  438. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/requirements.txt +0 -0
  439. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_auto_complete_on_finalize.py +0 -0
  440. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_bom_removed.py +0 -0
  441. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_build_api.py +0 -0
  442. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_completion_lock_order.py +0 -0
  443. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_item_recipe_api.py +0 -0
  444. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_item_workflow_api.py +0 -0
  445. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_labor_providers.py +0 -0
  446. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_manufacture_from_doc.py +0 -0
  447. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_manufacturing.py +0 -0
  448. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_manufacturing_import_idempotency.py +0 -0
  449. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_manufacturing_module.py +0 -0
  450. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_mfg_events.py +0 -0
  451. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_phase2_manufacturing_validations.py +0 -0
  452. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_production_order.py +0 -0
  453. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_recipe_costing.py +0 -0
  454. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_recipe_expansion.py +0 -0
  455. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_recost_api.py +0 -0
  456. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_run_records.py +0 -0
  457. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_to_make_allocation.py +0 -0
  458. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_where_used.py +0 -0
  459. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_work_centers_and_settings.py +0 -0
  460. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-manufacturing/tests/test_workflow_time.py +0 -0
  461. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/LICENSE +0 -0
  462. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/__init__.py +0 -0
  463. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/celerp_reports/__init__.py +0 -0
  464. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/celerp_reports/api_setup.py +0 -0
  465. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/celerp_reports/routes.py +0 -0
  466. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/celerp_reports/ui_routes.py +0 -0
  467. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/tests/test_reports_full.py +0 -0
  468. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-reports/tests/test_reports_unit.py +0 -0
  469. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-subscriptions/LICENSE +0 -0
  470. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-subscriptions/celerp_subscriptions/__init__.py +0 -0
  471. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-subscriptions/celerp_subscriptions/ui_routes.py +0 -0
  472. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-subscriptions/tests/test_subscriptions.py +0 -0
  473. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-subscriptions/tests/test_subscriptions_ui.py +0 -0
  474. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/LICENSE +0 -0
  475. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/__init__.py +0 -0
  476. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/__init__.py +0 -0
  477. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/accessory_fashion.json +0 -0
  478. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/activewear.json +0 -0
  479. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/art_photography.json +0 -0
  480. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/audio_equipment.json +0 -0
  481. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/bag_handbag.json +0 -0
  482. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/banknote.json +0 -0
  483. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/beauty_tool.json +0 -0
  484. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/bed_bedroom.json +0 -0
  485. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/beer.json +0 -0
  486. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/beverage_nonalc.json +0 -0
  487. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/body_part_auto.json +0 -0
  488. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/book.json +0 -0
  489. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/bottoms.json +0 -0
  490. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/brake_suspension.json +0 -0
  491. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/bullion_coin.json +0 -0
  492. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/camera.json +0 -0
  493. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/colored_stone.json +0 -0
  494. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/comic.json +0 -0
  495. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/commercial_space.json +0 -0
  496. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/component_part.json +0 -0
  497. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/confectionery.json +0 -0
  498. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/consulting_service.json +0 -0
  499. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/decorative_art.json +0 -0
  500. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/diamond.json +0 -0
  501. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/drawing.json +0 -0
  502. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/dress_jumpsuit.json +0 -0
  503. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_auto.json +0 -0
  504. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_component.json +0 -0
  505. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/emerald.json +0 -0
  506. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/engine_part.json +0 -0
  507. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/fastener.json +0 -0
  508. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/fertilizer_chemical.json +0 -0
  509. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/film_video.json +0 -0
  510. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/fine_writing_instrument.json +0 -0
  511. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/fluid_lubricant.json +0 -0
  512. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/footwear.json +0 -0
  513. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/fragrance.json +0 -0
  514. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_food.json +0 -0
  515. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_produce.json +0 -0
  516. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/frozen_food.json +0 -0
  517. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/gaming_console.json +0 -0
  518. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/gold_bullion.json +0 -0
  519. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/grain_cereal.json +0 -0
  520. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/haircare.json +0 -0
  521. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/hand_tool.json +0 -0
  522. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/ingredient_bulk.json +0 -0
  523. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/interior_part.json +0 -0
  524. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/jewelry.json +0 -0
  525. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/kitchen_dining.json +0 -0
  526. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/laptop.json +0 -0
  527. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/lighting.json +0 -0
  528. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/livestock_feed.json +0 -0
  529. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/makeup.json +0 -0
  530. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/measuring_instrument.json +0 -0
  531. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/medal_token.json +0 -0
  532. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/mineral_specimen.json +0 -0
  533. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/mobile_phone.json +0 -0
  534. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/music_cd.json +0 -0
  535. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/music_vinyl.json +0 -0
  536. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/nail.json +0 -0
  537. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/numismatic_coin.json +0 -0
  538. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/outdoor_furniture.json +0 -0
  539. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/outerwear.json +0 -0
  540. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/packaged_food.json +0 -0
  541. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/painting.json +0 -0
  542. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/parking_bay.json +0 -0
  543. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/pearl.json +0 -0
  544. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/personal_care.json +0 -0
  545. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/pipe_plumbing.json +0 -0
  546. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/platinum_bullion.json +0 -0
  547. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/power_tool.json +0 -0
  548. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/print_edition.json +0 -0
  549. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/residential_unit.json +0 -0
  550. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/rough_gemstone.json +0 -0
  551. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/ruby.json +0 -0
  552. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/saas_plan.json +0 -0
  553. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/safety_ppe.json +0 -0
  554. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/sapphire.json +0 -0
  555. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/sculpture.json +0 -0
  556. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/seating.json +0 -0
  557. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/seeds.json +0 -0
  558. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/silver_bullion.json +0 -0
  559. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/skincare.json +0 -0
  560. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/soft_furnishing.json +0 -0
  561. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/software_addon.json +0 -0
  562. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/software_license.json +0 -0
  563. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/spirit.json +0 -0
  564. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/storage_furniture.json +0 -0
  565. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/swimwear.json +0 -0
  566. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/table_desk.json +0 -0
  567. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/tablet.json +0 -0
  568. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/tire_wheel.json +0 -0
  569. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/tops.json +0 -0
  570. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/trading_card.json +0 -0
  571. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/tv_display.json +0 -0
  572. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/video_game.json +0 -0
  573. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/watch.json +0 -0
  574. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/watch_strap.json +0 -0
  575. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/categories/wine.json +0 -0
  576. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/agricultural.json +0 -0
  577. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/artwork.json +0 -0
  578. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/automotive.json +0 -0
  579. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/blank.json +0 -0
  580. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/books_media.json +0 -0
  581. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/coins_precious_metals.json +0 -0
  582. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/consulting.json +0 -0
  583. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/cosmetics.json +0 -0
  584. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/electronics.json +0 -0
  585. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/fashion.json +0 -0
  586. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/food_beverage.json +0 -0
  587. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/furniture.json +0 -0
  588. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/gemstones.json +0 -0
  589. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/hardware.json +0 -0
  590. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/property_rental.json +0 -0
  591. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/saas.json +0 -0
  592. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/watches.json +0 -0
  593. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/presets/wine_spirits.json +0 -0
  594. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/routes.py +0 -0
  595. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/celerp_verticals/ui_routes.py +0 -0
  596. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/tests/test_verticals.py +0 -0
  597. {celerp-2.3.4 → celerp-2.3.5}/default_modules/celerp-verticals/tests/test_verticals_routers.py +0 -0
  598. {celerp-2.3.4 → celerp-2.3.5}/legal/OFFICIAL-COMPONENTS.md +0 -0
  599. {celerp-2.3.4 → celerp-2.3.5}/legal/TRADEMARK.md +0 -0
  600. {celerp-2.3.4 → celerp-2.3.5}/packaging/winget/Celerp.Celerp.installer.yaml +0 -0
  601. {celerp-2.3.4 → celerp-2.3.5}/packaging/winget/Celerp.Celerp.locale.en-US.yaml +0 -0
  602. {celerp-2.3.4 → celerp-2.3.5}/packaging/winget/Celerp.Celerp.yaml +0 -0
  603. {celerp-2.3.4 → celerp-2.3.5}/packaging/winget/README.md +0 -0
  604. {celerp-2.3.4 → celerp-2.3.5}/pyproject.toml +0 -0
  605. {celerp-2.3.4 → celerp-2.3.5}/setup.cfg +0 -0
  606. {celerp-2.3.4 → celerp-2.3.5}/test_helpers.py +0 -0
  607. {celerp-2.3.4 → celerp-2.3.5}/ui/__init__.py +0 -0
  608. {celerp-2.3.4 → celerp-2.3.5}/ui/components/__init__.py +0 -0
  609. {celerp-2.3.4 → celerp-2.3.5}/ui/components/activity.py +0 -0
  610. {celerp-2.3.4 → celerp-2.3.5}/ui/components/attrs.py +0 -0
  611. {celerp-2.3.4 → celerp-2.3.5}/ui/components/backup.py +0 -0
  612. {celerp-2.3.4 → celerp-2.3.5}/ui/components/cloud_gate.py +0 -0
  613. {celerp-2.3.4 → celerp-2.3.5}/ui/components/currency.py +0 -0
  614. {celerp-2.3.4 → celerp-2.3.5}/ui/components/files.py +0 -0
  615. {celerp-2.3.4 → celerp-2.3.5}/ui/components/journal.py +0 -0
  616. {celerp-2.3.4 → celerp-2.3.5}/ui/components/notes.py +0 -0
  617. {celerp-2.3.4 → celerp-2.3.5}/ui/components/phone.py +0 -0
  618. {celerp-2.3.4 → celerp-2.3.5}/ui/components/report_kit.py +0 -0
  619. {celerp-2.3.4 → celerp-2.3.5}/ui/components/table.py +0 -0
  620. {celerp-2.3.4 → celerp-2.3.5}/ui/config.py +0 -0
  621. {celerp-2.3.4 → celerp-2.3.5}/ui/i18n.py +0 -0
  622. {celerp-2.3.4 → celerp-2.3.5}/ui/marketplace_catalog.py +0 -0
  623. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/__init__.py +0 -0
  624. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/account.py +0 -0
  625. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/accounting.py +0 -0
  626. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/accounting_import.py +0 -0
  627. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/contacts.py +0 -0
  628. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/csv_import.py +0 -0
  629. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/dashboard.py +0 -0
  630. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/docs_import.py +0 -0
  631. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/documents.py +0 -0
  632. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/events.py +0 -0
  633. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/financial_reports.py +0 -0
  634. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/lists_import.py +0 -0
  635. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/manufacturing.py +0 -0
  636. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/modules_page.py +0 -0
  637. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/reconciliation.py +0 -0
  638. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/reports.py +0 -0
  639. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_accounting.py +0 -0
  640. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_cloud.py +0 -0
  641. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_connectors.py +0 -0
  642. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_contacts.py +0 -0
  643. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_general.py +0 -0
  644. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_import.py +0 -0
  645. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_inventory.py +0 -0
  646. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_manufacturing.py +0 -0
  647. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_payments.py +0 -0
  648. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_purchasing.py +0 -0
  649. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/settings_sales.py +0 -0
  650. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/setup.py +0 -0
  651. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/subscriptions.py +0 -0
  652. {celerp-2.3.4 → celerp-2.3.5}/ui/routes/subscriptions_import.py +0 -0
  653. {celerp-2.3.4 → celerp-2.3.5}/ui/static/app.css +0 -0
  654. {celerp-2.3.4 → celerp-2.3.5}/ui/static/htmx.min.js +0 -0
  655. {celerp-2.3.4 → celerp-2.3.5}/ui/static/icon.png +0 -0
  656. {celerp-2.3.4 → celerp-2.3.5}/ui/static/logo.png +0 -0
  657. {celerp-2.3.4 → celerp-2.3.5}/ui/static/vendor/intl-tel-input/img/flags.webp +0 -0
  658. {celerp-2.3.4 → celerp-2.3.5}/ui/static/vendor/intl-tel-input/img/flags@2x.webp +0 -0
  659. {celerp-2.3.4 → celerp-2.3.5}/ui/static/vendor/intl-tel-input/intlTelInput.min.css +0 -0
  660. {celerp-2.3.4 → celerp-2.3.5}/ui/static/vendor/intl-tel-input/intlTelInput.min.js +0 -0
  661. {celerp-2.3.4 → celerp-2.3.5}/ui/static/vendor/intl-tel-input/intlTelInputWithUtils.min.js +0 -0
  662. {celerp-2.3.4 → celerp-2.3.5}/ui/static/vendor/intl-tel-input/utils.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: celerp
3
- Version: 2.3.4
3
+ Version: 2.3.5
4
4
  Summary: Free, self-hosted ERP for small businesses
5
5
  License: Business Source License 1.1
6
6
 
@@ -0,0 +1,22 @@
1
+ # Copyright (c) 2026 Noah Severs
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+ """Request-capacity constants shared by the API pool and the local UI transport.
4
+
5
+ The app launches one uvicorn worker (both `celerp start` and the Electron shell
6
+ run `uvicorn celerp.main:app` without `--workers`), so one API process owns one
7
+ request connection pool. These constants are the single source of truth for that
8
+ pool's size and for how many connections the web UI is allowed to open into that
9
+ process, so the two can never drift apart. The base size is the interactive
10
+ ceiling; the overflow is held back for background work, relay, auth, and bursts.
11
+
12
+ This module has no side effects and imports nothing from the app, so both the
13
+ database engine and the UI transport can read it without an import cycle.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ # Base connections the single API request pool keeps open, and the extra it may
18
+ # open under burst before refusing. The web UI's interactive transport uses the
19
+ # base size as its own connection ceiling, so a page fan-out can never demand
20
+ # more connections than the pool holds for interactive work.
21
+ REQUEST_DB_POOL_SIZE = 10
22
+ REQUEST_DB_MAX_OVERFLOW = 5
@@ -9,6 +9,7 @@ from sqlalchemy import text as _sql_text
9
9
  from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
10
10
  from sqlalchemy.pool import NullPool
11
11
 
12
+ from celerp.capacity import REQUEST_DB_MAX_OVERFLOW, REQUEST_DB_POOL_SIZE
12
13
  from celerp.config import settings
13
14
 
14
15
  # Shared advisory-lock key that serialises schema migrations across every process
@@ -33,11 +34,13 @@ def mask_db_credentials(text: str) -> str:
33
34
  _REQUEST_LOCK_TIMEOUT_MS = "3000"
34
35
  _REQUEST_STATEMENT_TIMEOUT_MS = "30000"
35
36
 
36
- # Pool budget: total_possible = (api_workers * (pool_size + max_overflow))
37
- # + (gui_workers * (gui_pool_size + gui_max_overflow))
38
- # Default workers 2 API + 1 GUI → 2*(10+5) + 1*(5+5) = 40 connections max.
39
- # Postgres default max_connections=100 leaves 60 for migrations, admin tools, etc.
40
- # If you increase worker counts, recalculate this budget before deploying.
37
+ # Pool budget: the app runs one API worker (both `celerp start` and the Electron
38
+ # shell launch uvicorn without --workers), so this single process owns one request
39
+ # pool of REQUEST_DB_POOL_SIZE base connections plus REQUEST_DB_MAX_OVERFLOW under
40
+ # burst. The base size is also the web UI's interactive connection ceiling, kept in
41
+ # lockstep through celerp.capacity so the two never drift. Postgres default
42
+ # max_connections=100 leaves ample headroom for migrations, admin tools, and
43
+ # background jobs beyond this pool.
41
44
  if os.environ.get("CELERP_TEST_NULLPOOL"):
42
45
  # Test mode: a fresh connection per use that closes on return, so a failed
43
46
  # test can't leave a poisoned/locked connection lingering in a pooled
@@ -49,8 +52,8 @@ else:
49
52
  settings.database_url,
50
53
  future=True,
51
54
  pool_pre_ping=True,
52
- pool_size=10,
53
- max_overflow=5,
55
+ pool_size=REQUEST_DB_POOL_SIZE,
56
+ max_overflow=REQUEST_DB_MAX_OVERFLOW,
54
57
  # Bound how long any query may wait on a lock or run, so a stuck query is
55
58
  # cancelled instead of pinning one of the few pooled connections for the
56
59
  # full request lifetime (lock_timeout 3s, statement_timeout 30s, in ms).
@@ -26,6 +26,7 @@ from fastapi.staticfiles import StaticFiles
26
26
  from celerp.routers import auth, companies, ledger
27
27
  from celerp.routers import health, notifications, system, events as events_router_mod
28
28
  from celerp.routers import stars as stars_router_mod
29
+ from celerp.routers import search as search_router_mod
29
30
 
30
31
  import celerp.models # noqa: F401 - ensures kernel models (UserCompany, ImportBatch, DocShareToken) are registered
31
32
 
@@ -466,6 +467,7 @@ app.include_router(system.router, prefix="/system", tags=["system"])
466
467
  app.include_router(stars_router_mod.router, prefix="/stars", tags=["stars"])
467
468
  app.include_router(notifications.router)
468
469
  app.include_router(events_router_mod.router)
470
+ app.include_router(search_router_mod.router, tags=["search"])
469
471
 
470
472
  # Backup router — always registered; individual endpoints gate on cloud connection.
471
473
  # celerp_backup lives in default_modules/celerp-backup/ which is not on sys.path
@@ -35,6 +35,7 @@ import functools
35
35
  import hashlib
36
36
  import importlib
37
37
  import importlib.util
38
+ import inspect
38
39
  import json
39
40
  import logging
40
41
  import os
@@ -45,7 +46,7 @@ from pathlib import Path
45
46
  from celerp.modules.importer import PREMIUM_MARKER
46
47
  from celerp.modules.license import check_license, exchange_api_key_for_jwt, is_premium_path
47
48
  from celerp.modules.meta import META_FILENAME
48
- from celerp.modules.slots import register as register_slot
49
+ from celerp.modules.slots import register as register_slot, resolve_handler
49
50
  from celerp.services.permissions import is_permission_key
50
51
 
51
52
  log = logging.getLogger(__name__)
@@ -808,10 +809,16 @@ def _load_one(pkg_path: Path, pkg_name: str, *, trusted: bool = False) -> dict |
808
809
  f" {_MODULE_AI_API_URL}"
809
810
  )
810
811
 
812
+ slots_manifest = manifest.get("slots") or {}
813
+
811
814
  # A slot item naming a permission key outside the registry would KeyError in
812
815
  # the sidebar builder on every page render, taking the whole UI down for
813
- # every user. Refuse the module here, with the bad key named, instead.
814
- for slot_name, contribution in (manifest.get("slots") or {}).items():
816
+ # every user. Refuse the module here, with the bad key named, instead. The
817
+ # search_provider slot has its own stricter validation below (which also
818
+ # checks its permission), so it is skipped here.
819
+ for slot_name, contribution in slots_manifest.items():
820
+ if slot_name == _SEARCH_PROVIDER_SLOT:
821
+ continue
815
822
  items = contribution if isinstance(contribution, list) else [contribution]
816
823
  for item in items:
817
824
  perm = item.get("permission") if isinstance(item, dict) else None
@@ -829,14 +836,38 @@ def _load_one(pkg_path: Path, pkg_name: str, *, trusted: bool = False) -> dict |
829
836
  f"closest existing key."
830
837
  )
831
838
 
832
- # Register extension slots
833
- for slot_name, contribution in (manifest.get("slots") or {}).items():
839
+ # Validate the search_provider descriptor and resolve its handler BEFORE any
840
+ # slot is registered, so a broken provider rejects the whole module cleanly
841
+ # (no half-registered slots) rather than first surfacing as a degraded source
842
+ # when a user types into search.
843
+ prepared_search_provider = None
844
+ if _SEARCH_PROVIDER_SLOT in slots_manifest:
845
+ try:
846
+ prepared_search_provider = _prepare_search_provider(
847
+ pkg_name, pkg_path, slots_manifest[_SEARCH_PROVIDER_SLOT],
848
+ trusted=trusted,
849
+ )
850
+ except ModuleLoadError:
851
+ log.error("Module %r rejected: invalid search_provider slot", pkg_name)
852
+ for key in list(sys.modules.keys()):
853
+ if key == pkg_name or key.startswith(pkg_name + "."):
854
+ sys.modules.pop(key, None)
855
+ raise
856
+
857
+ # Register extension slots (search_provider is registered from its prepared
858
+ # descriptor below, never through the generic path).
859
+ for slot_name, contribution in slots_manifest.items():
860
+ if slot_name == _SEARCH_PROVIDER_SLOT:
861
+ continue
834
862
  if isinstance(contribution, dict):
835
863
  register_slot(slot_name, {**contribution, "_module": pkg_name})
836
864
  elif isinstance(contribution, list):
837
865
  for item in contribution:
838
866
  register_slot(slot_name, {**item, "_module": pkg_name})
839
867
 
868
+ if prepared_search_provider is not None:
869
+ register_slot(_SEARCH_PROVIDER_SLOT, prepared_search_provider)
870
+
840
871
  # Register module-contributed UI translation catalogs (the `locales`
841
872
  # manifest key, mirroring `slots` above). Each entry maps a language code to
842
873
  # {"file": <path>, "rtl": <bool>}. Pushed into ui.i18n through a lazy import
@@ -1004,6 +1035,31 @@ def _flag_dynamic_import(node: ast.Call, violations: set[str]) -> None:
1004
1035
  violations.add(hit)
1005
1036
 
1006
1037
 
1038
+ def _module_source_file(pkg_path: Path, dotted_module_path: str) -> Path | None:
1039
+ """The local ``.py`` (or package ``__init__.py``) inside ``pkg_path`` that a
1040
+ dotted module path names, or None if no such source lives in the installed
1041
+ module tree.
1042
+
1043
+ Handles both the flat layout (``pkg_path`` IS the top-level package, its
1044
+ folder name == the package) and the nested GitHub-style layout (the package
1045
+ sits one level in, at ``pkg_path/<top_pkg>``). Used to prove a search
1046
+ handler's source is owned by the module before core imports it, and to seed
1047
+ the protected-BSL AST scan from that same file.
1048
+ """
1049
+ parts = dotted_module_path.split(".")
1050
+ if not parts or not parts[0]:
1051
+ return None
1052
+ top_pkg = parts[0]
1053
+ pkg_dir = pkg_path if pkg_path.name == top_pkg else pkg_path / top_pkg
1054
+ entry = pkg_dir.joinpath(*parts[1:]).with_suffix(".py")
1055
+ if entry.exists():
1056
+ return entry
1057
+ entry = pkg_dir.joinpath(*parts[1:], "__init__.py")
1058
+ if entry.exists():
1059
+ return entry
1060
+ return None
1061
+
1062
+
1007
1063
  def _ast_scan_module_file(pkg_path: Path, dotted_module_path: str) -> set[str]:
1008
1064
  """Protected-BSL-internal imports reachable from the given entry module.
1009
1065
 
@@ -1038,10 +1094,8 @@ def _ast_scan_module_file(pkg_path: Path, dotted_module_path: str) -> set[str]:
1038
1094
  return cand
1039
1095
  return None
1040
1096
 
1041
- entry = pkg_dir.joinpath(*parts[1:]).with_suffix(".py")
1042
- if not entry.exists():
1043
- entry = pkg_dir.joinpath(*parts[1:], "__init__.py")
1044
- if not entry.exists():
1097
+ entry = _module_source_file(pkg_path, dotted_module_path)
1098
+ if entry is None:
1045
1099
  return set()
1046
1100
 
1047
1101
  violations: set[str] = set()
@@ -1084,3 +1138,172 @@ def _ast_scan_module_file(pkg_path: Path, dotted_module_path: str) -> set[str]:
1084
1138
  elif isinstance(node, ast.Call):
1085
1139
  _flag_dynamic_import(node, violations)
1086
1140
  return violations
1141
+
1142
+
1143
+ # The search_provider slot has a stricter contract than the generic slots: a
1144
+ # single descriptor (never a list), a closed key set, and a locally-owned async
1145
+ # handler resolved at load time. The template linter mirrors these exactly.
1146
+ _SEARCH_PROVIDER_SLOT = "search_provider"
1147
+ _SEARCH_PROVIDER_KEYS = frozenset({"handler", "result_key", "permission"})
1148
+ _SEARCH_RESULT_KEYS = frozenset({"items", "entries"})
1149
+
1150
+
1151
+ def _enclosing_first_party_module(source_file: Path, expected_name: str) -> Path | None:
1152
+ """The nearest ancestor directory of ``source_file`` that is a content-verified
1153
+ first-party module folder named ``expected_name``, or None.
1154
+
1155
+ Used to accept a first-party module whose handler resolves to the SAME
1156
+ first-party module already loaded from another location (a shipped default
1157
+ scanned from two roots - e.g. the repo copy and a reseeded copy). is_first_party
1158
+ requires the lock name AND a matching content digest, so a match here is
1159
+ content-identical to the module being loaded; a resolution to core, or to any
1160
+ other module, has no such ancestor and is rejected.
1161
+ """
1162
+ for parent in source_file.parents:
1163
+ if parent.name == expected_name and is_first_party(parent):
1164
+ return parent
1165
+ return None
1166
+
1167
+
1168
+ def _handler_source_owned(
1169
+ proof: str | None, pkg_root: str, pkg_name: str, trusted: bool
1170
+ ) -> bool:
1171
+ """True if a resolved handler/module source file legitimately belongs to the
1172
+ module being loaded.
1173
+
1174
+ It must live under the module's own package root. For a content-verified
1175
+ first-party module ONLY, a source under a different copy of the SAME first-party
1176
+ module (same lock name and verified digest) is also legitimate - the one case
1177
+ where importlib returns an identically-named default already loaded from another
1178
+ root. ``is_relative_to`` returns False for paths on different drives rather than
1179
+ raising, so it needs no cross-drive guard. Never accepts a resolution to core or
1180
+ to a different module, and every untrusted module is held to strict same-tree.
1181
+ """
1182
+ if not proof:
1183
+ return False
1184
+ real = Path(os.path.realpath(proof))
1185
+ if real.is_relative_to(pkg_root):
1186
+ return True
1187
+ if not trusted:
1188
+ return False
1189
+ return _enclosing_first_party_module(real, pkg_name) is not None
1190
+
1191
+
1192
+ def _prepare_search_provider(
1193
+ pkg_name: str, pkg_path: Path, contribution, *, trusted: bool
1194
+ ) -> dict:
1195
+ """Validate a ``search_provider`` descriptor and resolve its handler at load
1196
+ time, returning the runtime descriptor to register.
1197
+
1198
+ The slot takes exactly one dict: one module, one provider, one results
1199
+ bucket, so a module can never overwrite its own search bucket. The descriptor
1200
+ must carry exactly ``{handler, result_key, permission}`` (extra keys are
1201
+ rejected, never ignored, so a misspelling fails loudly); ``result_key`` is one
1202
+ of ``{items, entries}``; ``permission`` is a known key. The handler
1203
+ ``module:function`` must name source that lives inside this module's own tree,
1204
+ must import no protected BSL internal (third-party only), and must resolve at
1205
+ load to an async callable. A provider that cannot pass all of this fails
1206
+ module load rather than first surfacing as a degraded source when a user types
1207
+ into search. Raises :class:`ModuleLoadError` on any violation.
1208
+ """
1209
+ if not isinstance(contribution, dict):
1210
+ raise ModuleLoadError(
1211
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} takes exactly one descriptor dict, "
1212
+ f"not a {type(contribution).__name__}."
1213
+ )
1214
+ keys = set(contribution)
1215
+ if keys != set(_SEARCH_PROVIDER_KEYS):
1216
+ missing = sorted(_SEARCH_PROVIDER_KEYS - keys)
1217
+ extra = sorted(keys - _SEARCH_PROVIDER_KEYS)
1218
+ raise ModuleLoadError(
1219
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} descriptor keys must be exactly "
1220
+ f"{sorted(_SEARCH_PROVIDER_KEYS)} (missing={missing}, extra={extra})."
1221
+ )
1222
+ result_key = contribution["result_key"]
1223
+ if result_key not in _SEARCH_RESULT_KEYS:
1224
+ raise ModuleLoadError(
1225
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} result_key {result_key!r} must be one "
1226
+ f"of {sorted(_SEARCH_RESULT_KEYS)}."
1227
+ )
1228
+ perm = contribution["permission"]
1229
+ if not is_permission_key(perm):
1230
+ raise ModuleLoadError(
1231
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} names unknown permission key {perm!r}."
1232
+ )
1233
+ handler_path = contribution["handler"]
1234
+ if not isinstance(handler_path, str) or handler_path.count(":") != 1:
1235
+ raise ModuleLoadError(
1236
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} must be "
1237
+ f"'module.path:function'."
1238
+ )
1239
+ module_path, func_name = handler_path.split(":", 1)
1240
+ if not module_path or not func_name:
1241
+ raise ModuleLoadError(
1242
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} must name a "
1243
+ f"non-empty module path and function."
1244
+ )
1245
+ # Local ownership: the handler must resolve to source inside this module's own
1246
+ # tree, so a manifest can never point core at 'celerp.some_internal:fn' and
1247
+ # have it imported on demand around the protected-import gate.
1248
+ if _module_source_file(pkg_path, module_path) is None:
1249
+ raise ModuleLoadError(
1250
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} does not "
1251
+ f"resolve to source inside module {pkg_name!r}."
1252
+ )
1253
+ # The handler is a lazily-imported entry point, so it goes through the same
1254
+ # transitive protected-BSL scan as the route entry modules (third-party only).
1255
+ if not trusted:
1256
+ violations = _ast_scan_module_file(pkg_path, module_path)
1257
+ if violations:
1258
+ raise ModuleLoadError(
1259
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler imports protected BSL "
1260
+ f"internals ({', '.join(sorted(violations))})."
1261
+ )
1262
+ try:
1263
+ handler = resolve_handler(handler_path)
1264
+ except Exception as exc:
1265
+ raise ModuleLoadError(
1266
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} failed to "
1267
+ f"resolve ({type(exc).__name__})."
1268
+ )
1269
+ if not callable(handler):
1270
+ raise ModuleLoadError(
1271
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} is not callable."
1272
+ )
1273
+ if not inspect.iscoroutinefunction(handler):
1274
+ raise ModuleLoadError(
1275
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} must be async; "
1276
+ f"the aggregator awaits it."
1277
+ )
1278
+ # Provenance: an on-disk file matching the dotted path is not proof of what
1279
+ # importlib actually resolved. A decoy source shipped inside the module's own
1280
+ # tree (e.g. a celerp/ai/service.py) satisfies the existence and AST checks
1281
+ # above, yet importlib returns the already-loaded REAL core module of the same
1282
+ # dotted name, binding the provider to arbitrary code. Require that BOTH the
1283
+ # resolved module's file AND the handler's own source file be owned by this
1284
+ # module (_handler_source_owned): under its own package root, or - for a
1285
+ # content-verified first-party module only - inside the same first-party module
1286
+ # (same lock name and digest) loaded from another root. realpath collapses
1287
+ # symlinks and '..' so neither can point a proof outside the tree. This runs for
1288
+ # every module: a first-party manifest whose handler resolves to core, or to a
1289
+ # different module, is rejected exactly as an untrusted decoy is.
1290
+ pkg_root = os.path.realpath(pkg_path)
1291
+ try:
1292
+ resolved_module = importlib.import_module(module_path)
1293
+ module_file = getattr(resolved_module, "__file__", None)
1294
+ handler_file = inspect.getsourcefile(inspect.unwrap(handler))
1295
+ except Exception as exc:
1296
+ raise ModuleLoadError(
1297
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} source could "
1298
+ f"not be located ({type(exc).__name__})."
1299
+ )
1300
+ for proof in (module_file, handler_file):
1301
+ if not _handler_source_owned(proof, pkg_root, pkg_name, trusted):
1302
+ raise ModuleLoadError(
1303
+ f"Slot {_SEARCH_PROVIDER_SLOT!r} handler {handler_path!r} resolves to "
1304
+ f"source outside module {pkg_name!r}'s own package tree."
1305
+ )
1306
+ # Runtime-owned trust metadata is injected AFTER the manifest contribution, and
1307
+ # the closed key set above already rejects a manifest that tries to supply
1308
+ # _module / _first_party itself, so neither can be spoofed.
1309
+ return {**contribution, "_module": pkg_name, "_first_party": trusted}
@@ -17,6 +17,14 @@ import_adapter Source option in the CSV import page
17
17
  category_schema Default field definitions for a named category
18
18
  projection_handler Maps event-type prefixes to a handler function
19
19
  on_company_created Async callback(session, company_id) fired after a new company is persisted
20
+ search_provider Contributes rows to the global search bar. Exactly one descriptor
21
+ dict per module: {"handler", "result_key", "permission"}. handler
22
+ names an in-module "module.path:function" resolved and validated
23
+ async at load, invoked as
24
+ `async def handler(session, company_id, role, q, limit) -> dict`
25
+ returning {result_key: [rows]}; result_key is "items" or "entries";
26
+ permission gates the source per company role. See the module loader
27
+ for the full descriptor contract.
20
28
 
21
29
  Usage in core UI
22
30
  ----------------
@@ -29,9 +37,26 @@ Usage in core UI
29
37
  """
30
38
  from __future__ import annotations
31
39
 
40
+ from typing import Callable
41
+
32
42
  _slots: dict[str, list[dict]] = {}
33
43
 
34
44
 
45
+ def resolve_handler(dotted: str) -> Callable:
46
+ """Resolve a "module.path:function" string to the callable it names.
47
+
48
+ Raises ImportError if the module cannot be imported and AttributeError if
49
+ the module has no such attribute. Callers wrap this in their own try/except
50
+ to apply their failure policy (swallow, propagate, log-and-skip); the shared
51
+ resolver never decides that policy, it only does the import and lookup.
52
+ """
53
+ import importlib
54
+
55
+ module_path, func_name = dotted.rsplit(":", 1)
56
+ mod = importlib.import_module(module_path)
57
+ return getattr(mod, func_name)
58
+
59
+
35
60
  def register(slot: str, contribution: dict) -> None:
36
61
  """Register a module contribution into a named slot.
37
62
 
@@ -64,7 +89,6 @@ async def fire_lifecycle(slot: str, **kwargs) -> None:
64
89
  (with traceback) and swallowed, so a recurrence surfaces as an alert
65
90
  instead of vanishing.
66
91
  """
67
- import importlib
68
92
  import logging
69
93
 
70
94
  _log = logging.getLogger(__name__)
@@ -74,9 +98,7 @@ async def fire_lifecycle(slot: str, **kwargs) -> None:
74
98
  if not handler_path:
75
99
  continue
76
100
  try:
77
- mod_path, func_name = handler_path.rsplit(":", 1)
78
- mod = importlib.import_module(mod_path)
79
- func = getattr(mod, func_name)
101
+ func = resolve_handler(handler_path)
80
102
  await func(**kwargs)
81
103
  except Exception as exc:
82
104
  _log.exception(
@@ -90,7 +112,6 @@ async def fire_lifecycle_strict(slot_name: str, **kwargs) -> None:
90
112
 
91
113
  Use for slots where a handler must be able to block the action.
92
114
  """
93
- import importlib
94
115
  import logging
95
116
  from fastapi import HTTPException
96
117
 
@@ -101,9 +122,7 @@ async def fire_lifecycle_strict(slot_name: str, **kwargs) -> None:
101
122
  if not handler_path:
102
123
  continue
103
124
  try:
104
- mod_path, func_name = handler_path.rsplit(":", 1)
105
- mod = importlib.import_module(mod_path)
106
- func = getattr(mod, func_name)
125
+ func = resolve_handler(handler_path)
107
126
  await func(**kwargs)
108
127
  except HTTPException:
109
128
  raise
@@ -3,7 +3,6 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
- import importlib
7
6
  import logging
8
7
  from datetime import datetime, timezone
9
8
 
@@ -18,11 +17,15 @@ log = logging.getLogger(__name__)
18
17
 
19
18
 
20
19
  def _resolve_module_handler(dotted: str):
21
- """Import and return a handler callable from a 'module.path:function' string."""
20
+ """Import and return a handler callable from a 'module.path:function' string.
21
+
22
+ Returns None on any resolution failure so a single bad projection_handler
23
+ slot cannot stop the engine from picking up its siblings.
24
+ """
25
+ from celerp.modules.slots import resolve_handler
26
+
22
27
  try:
23
- module_path, func_name = dotted.rsplit(":", 1)
24
- mod = importlib.import_module(module_path)
25
- return getattr(mod, func_name)
28
+ return resolve_handler(dotted)
26
29
  except Exception as exc:
27
30
  log.error("ProjectionEngine: cannot resolve module handler %r: %s", dotted, exc)
28
31
  return None