exobrain-database 0.2.0__tar.gz → 0.3.0__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 (175) hide show
  1. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/PKG-INFO +46 -27
  2. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/README.md +43 -17
  3. exobrain_database-0.3.0/pyproject.toml +113 -0
  4. exobrain_database-0.2.0/pyproject.toml → exobrain_database-0.3.0/pyproject.toml.orig +16 -4
  5. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/__init__.py +1 -1
  6. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/alembic.ini +1 -1
  7. exobrain_database-0.3.0/src/exobrain/database/migrations/cli.py +72 -0
  8. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/env.py +30 -23
  9. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/migration_manager.py +5 -1
  10. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_04_20_1015-8f3c5e2d9a1b_add_running_action_summary_table_with_text_column.py +2 -0
  11. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_04_30_1357-c3e8047f29f6_add_kpi_names_to_predefined_action.py +1 -1
  12. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_07_22_1210-f1a2b3c4d5e6_add_reporting_field_tables.py +132 -0
  13. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_04_1241-d4e8f2a6b1c3_add_editable_fields_to_action_conf.py +36 -0
  14. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1508-de9cdd9d1f23_convert_running_status_columns_to_postgres_enums.py +209 -0
  15. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1510-102986454ad1_migrate_deprecated_running_statuses.py +297 -0
  16. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1512-9e35d31c23bf_drop_deprecated_running_status_enum_values.py +271 -0
  17. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1514-a7f3c21d8b04_add_running_status_timestamps.py +79 -0
  18. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1620-b8d47a1c9e02_migrate_widget_conf_deprecated_statuses.py +419 -0
  19. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_03_0910-c1f7a4be3d58_add_org_stop_risk_role_and_permission.py +239 -0
  20. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_03_0915-a3d92c07fb14_add_stop_risk_params_to_action_conf.py +105 -0
  21. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_07_1000-cf5954e2447b_move_stop_risk_params_to_risk_conf.py +181 -0
  22. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_07_1005-dde1d89b4372_add_stop_risk_snapshot_to_running_risk.py +127 -0
  23. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_09_0910-f7d0d5c816d5_store_running_action_kpis_in_kpi_mapping.py +180 -0
  24. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_11_0900-01c09dcf16bd_add_running_action_error_table.py +183 -0
  25. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_11_1100-e21b7f4a9c86_remove_error_data_scopes.py +130 -0
  26. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_17_1400-035a82018e8a_add_ctx_element_indexes_to_running_risk.py +61 -0
  27. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_19_1500-5a24d1db4aee_add_running_action_category_table.py +146 -0
  28. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_23_1656-cb0f9bd0b7e6_create_trans_table.py +55 -0
  29. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_10_01_1000-b29a8020ead0_add_org_export_risk_role_and_permission.py +240 -0
  30. exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_10_02_1000-7b2d4f1c9a60_add_running_risk_sequence.py +111 -0
  31. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/base.py +9 -4
  32. exobrain_database-0.3.0/src/exobrain/database/model/enums/__init__.py +21 -0
  33. exobrain_database-0.3.0/src/exobrain/database/model/enums/config.py +61 -0
  34. exobrain_database-0.3.0/src/exobrain/database/model/enums/context.py +20 -0
  35. exobrain_database-0.3.0/src/exobrain/database/model/enums/reporting.py +15 -0
  36. exobrain_database-0.3.0/src/exobrain/database/model/enums/running.py +104 -0
  37. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/field_types.py +3 -0
  38. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/copilot.py +1 -1
  39. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/organization_models.py +4 -4
  40. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/predefined_models.py +6 -6
  41. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/reason_models.py +18 -0
  42. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/__init__.py +9 -4
  43. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/config_models.py +58 -4
  44. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/dashboard_models.py +2 -2
  45. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/org_base.py +1 -1
  46. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/organization_settings.py +3 -3
  47. exobrain_database-0.3.0/src/exobrain/database/model/org/report_models.py +135 -0
  48. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/running_models.py +453 -45
  49. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/scope.py +10 -10
  50. exobrain_database-0.3.0/src/exobrain/database/model/org/trans.py +44 -0
  51. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/user.py +3 -3
  52. exobrain_database-0.3.0/src/exobrain/database/tools/report_field_coercion.py +64 -0
  53. exobrain_database-0.3.0/src/exobrain/database/tools/risk_report_projector.py +180 -0
  54. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/sql_query_logger.py +5 -5
  55. exobrain_database-0.2.0/src/exobrain/database/model/enums/__init__.py +0 -15
  56. exobrain_database-0.2.0/src/exobrain/database/model/enums/config.py +0 -30
  57. exobrain_database-0.2.0/src/exobrain/database/model/enums/running.py +0 -87
  58. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/LICENSE.md +0 -0
  59. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/__init__.py +0 -0
  60. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/README.md +0 -0
  61. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/script.py.mako +0 -0
  62. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_08_17_0937-3ed3cf31c9d4_.py +0 -0
  63. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_08_31_1322-aa6854636eac_.py +0 -0
  64. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_01_0925-9667f0608380_.py +0 -0
  65. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_13_1243-3cd1eb0d7b52_.py +0 -0
  66. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_15_1447-52f33bc03521_.py +0 -0
  67. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_19_0956-f8e096a41120_.py +0 -0
  68. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_21_1642-74f18c0bab6e_.py +0 -0
  69. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_28_1237-919ce06afab1_.py +0 -0
  70. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_04_0718-03535f8dfe5f_.py +0 -0
  71. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_05_1508-f64d4c00b610_.py +0 -0
  72. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_06_0819-e544518a415c_.py +0 -0
  73. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_06_1312-b9b232d63be3_.py +0 -0
  74. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_25_0902-aab08fb68941_.py +0 -0
  75. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_25_0937-d59ec80e6dd7_.py +0 -0
  76. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_22_1628-84b116f3df26_.py +0 -0
  77. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_22_1654-bcb01e365c42_.py +0 -0
  78. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_27_1045-00ce519af235_.py +0 -0
  79. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_27_1048-f779dc9fe429_.py +0 -0
  80. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_29_1421-ad2b4c9c38fe_.py +0 -0
  81. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_12_04_1029-f91d936478fb_.py +0 -0
  82. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_12_11_1104-b33e0d6a5bdd_.py +0 -0
  83. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_12_18_1406-73ac94585923_.py +0 -0
  84. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_05_1022-f231770c573e_.py +0 -0
  85. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_17_1606-b94c145b2310_.py +0 -0
  86. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_18_1547-c450c961dfd0_.py +0 -0
  87. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_18_1855-7101980bc238_.py +0 -0
  88. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_22_1616-a35a2828dbcd_.py +0 -0
  89. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_04_1549-4cc4ffdb6c02_.py +0 -0
  90. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_13_1323-97a9ef3f38c3_.py +0 -0
  91. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_20_1033-13bc4d2ab3ab_.py +0 -0
  92. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_28_0905-ffd01ebb2c87_.py +0 -0
  93. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_28_1332-33744d8620d3_.py +0 -0
  94. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_04_05_0919-a14d98908583_.py +0 -0
  95. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_04_29_1515-882409414d37_.py +0 -0
  96. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_05_23_0959-24bb8fdb3ba7_.py +0 -0
  97. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_05_24_1248-f2a78a625a74_.py +0 -0
  98. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_06_07_1537-004b611f77cf_.py +0 -0
  99. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_06_10_1306-f0fe99d57963_.py +0 -0
  100. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_10_15_0646-ef0829fe3540_.py +0 -0
  101. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_01_28_1020-ea2ebd0e2cdc_.py +0 -0
  102. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_03_19_1341-adeeb7c46a3c_.py +0 -0
  103. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_03_25_1449-8fb5b2059d5a_.py +0 -0
  104. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_06_1503-88aa2ef323c5-org.json +0 -0
  105. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_06_1503-88aa2ef323c5-public.json +0 -0
  106. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_06_1503-88aa2ef323c5_add_constraints_to_fk.py +0 -0
  107. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_20_1302-37f7dbf56615_add_is_learning_field_to_license.py +0 -0
  108. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_21_0839-096c1ab6ea15_add_is_learning_field_to_predefined_.py +0 -0
  109. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_03_0336-60d91382b626_add_grace_period_field_to_risk_conf.py +0 -0
  110. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_17_1013-4894e248a31d_add_risk_conf_buffer_period_field_to_.py +0 -0
  111. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_20_0845-c0e0c905cfb1_add_computing_strategy.py +0 -0
  112. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_20_0919-360b6879ae25_add_fully_computed_field_to_running_.py +0 -0
  113. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_21_1200-1a37475a962d_fix_feasible_field_in_running_risk_table_set_not_null.py +0 -0
  114. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_21_1300-d456be82025a_add_computed_mapping_field_in_running_.py +0 -0
  115. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0154-317d388748a1_adding_auto_rejected_reason_code.py +0 -0
  116. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0227-0a9522eb04f0_update_predefined_actions_execution.py +0 -0
  117. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0610-9daee7d935b1_add_rejection_and_expiration_fields.py +0 -0
  118. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0617-ee6062e6dc4d_add_rejection_and_expiration_fields.py +0 -0
  119. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_29_0828-90923eeab038_calculate_due_dates_and_due_indicators.py +0 -0
  120. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_09_26_1624-2716d77c7904_make_context_fields_non_nullable.py +0 -0
  121. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_09_26_1857-0ab6e7d1a127_add_note_column_to_running_action.py +0 -0
  122. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_10_17_1620-6400ea4ce6f0_add_index_overdue_risks.py +0 -0
  123. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_10_31_0222-67c46f78caca_convert_action_context_data_json_to_jsonb.py +0 -0
  124. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_11_04_2117-a8a814d7f2ea_rename_execution_reason_code.py +0 -0
  125. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_04_1647-87c0d5fd2688_apply_new_naming_rules_for_indexes.py +0 -0
  126. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_04_1801-392b727bbaa1_remove_unused_exo_conf_table.py +0 -0
  127. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_0840-4b12100a932c_add_constraints_to_organizations_settings.py +0 -0
  128. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_0917-f67bd91a1913_change_copilot_uiConfiguration_json_to_jsonb.py +0 -0
  129. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_0935-87de8335f045_constrain_organizations_preferences_fields.py +0 -0
  130. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_1018-7271b6d49e2c_enforce_not_null_and_jsonb_for_predefined_tables.py +0 -0
  131. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_1510-711567521aa6_convert_config_tables_json_to_jsonb.py +0 -0
  132. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_1540-ce5a35090a82_convert_connection_json_to_jsonb.py +0 -0
  133. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_06_0939-115812c0bcd6_make_scope_key_non_nullable.py +0 -0
  134. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_06_1109-7dd6b5f271ed_convert_json_to_jsonb_for_dashboard_and_widgets.py +0 -0
  135. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_06_1452-4e4ad858fdf9_convert_json_to_jsonb_for_running_entities.py +0 -0
  136. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_09_1558-6954766729aa_simplify_one_to_many_relationships.py +0 -0
  137. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_12_1639-e548f437e5de_simplify_one_to_many_relationships.py +0 -0
  138. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_02_03_1456-abbb5a630567_simplify_one_to_many_relationships.py +0 -0
  139. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_02_06_0827-95438a5ec210_simplify_one_to_many_relationships.py +0 -0
  140. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_02_06_0835-881f104f8b2b_simplify_one_to_many_relationships.py +0 -0
  141. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_05_07_0100-a1b2c3d4e5f6_create_scores_table.py +0 -0
  142. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_06_29_1324-b23761c01aac_add_updated_data_to_running_action_context.py +0 -0
  143. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_06_29_1500-c5a9e1f3b7d2_add_widget_executive_view_fields.py +0 -0
  144. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/__init__.py +0 -0
  145. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/__init__.py +0 -0
  146. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/action_conf_action_reason.py +0 -0
  147. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/copilot_license.py +0 -0
  148. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/exec_conf_execution_reason.py +0 -0
  149. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_action_action_reason.py +0 -0
  150. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_action_predefined_risk.py +0 -0
  151. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_execution_execution_reason.py +0 -0
  152. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_execution_predefined_action.py +0 -0
  153. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_risk_risk_reason.py +0 -0
  154. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/risk_conf_risk_reason.py +0 -0
  155. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_action_conf.py +0 -0
  156. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_exec_conf.py +0 -0
  157. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_permissions.py +0 -0
  158. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_predefined_action.py +0 -0
  159. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_predefined_execution.py +0 -0
  160. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_running_actions.py +0 -0
  161. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_running_executions.py +0 -0
  162. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_users.py +0 -0
  163. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/running_action_context_scopes.py +0 -0
  164. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/users_scopes.py +0 -0
  165. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/enums/currency.py +0 -0
  166. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/enums/dashboard.py +0 -0
  167. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/__init__.py +2 -2
  168. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/general_base.py +0 -0
  169. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/permission.py +0 -0
  170. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/role.py +0 -0
  171. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/connection.py +0 -0
  172. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/py.typed +0 -0
  173. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/__init__.py +0 -0
  174. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/jsonb_filter.py +0 -0
  175. {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/record_count.py +0 -0
@@ -1,17 +1,11 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: exobrain-database
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Exobrain database model and migration management
5
5
  Keywords:
6
6
  Author: Laurent LAPORTE
7
7
  Author-email: Laurent LAPORTE <laurent@dfya.io>
8
- License: Copyright © 2025-present DFYA SAS, All rights reserved.
9
-
10
- This is a private project.
11
- All rights reserved.
12
-
13
- The content of this repository is intended for private use only.
14
- Reproduction, distribution, or disclosure to third parties, in whole or in part, is strictly prohibited without the explicit written permission of the copyright holder.
8
+ License-File: LICENSE.md
15
9
  Classifier: Development Status :: 4 - Beta
16
10
  Classifier: Programming Language :: Python
17
11
  Classifier: Programming Language :: Python :: 3.12
@@ -20,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.14
20
14
  Classifier: Topic :: Software Development :: Libraries
21
15
  Classifier: Topic :: Database
22
16
  Classifier: Topic :: Database :: Database Engines/Servers
23
- Classifier: License :: Other/Proprietary License
24
17
  Requires-Dist: alembic>=1.18.4
25
18
  Requires-Dist: psycopg[binary]>=3.3.4
26
19
  Requires-Dist: sqlalchemy>=2.0.51
@@ -134,6 +127,29 @@ For creating a new migration, pass `-c` explicitly so the file naming template f
134
127
  alembic -c src/exobrain/database/migrations/alembic.ini revision --autogenerate -m "short description"
135
128
  ```
136
129
 
130
+ #### Running migrations from outside this repository
131
+
132
+ The `alembic` CLI above only works from this project's root, since it relies on the `[tool.alembic]`
133
+ section of this repo's `pyproject.toml`. Consuming projects (e.g. `exobrain-server`) or containers that
134
+ only have `exobrain-database` installed as a dependency don't have that file, and the packaged
135
+ `alembic.ini` sits inside the installed package (e.g.: under `.venv/`), which is impractical to locate.
136
+
137
+ For that case, `exobrain-database` ships a console script, `exobrain-db-migrate`, that resolves its own
138
+ `alembic.ini` and wraps the full Alembic CLI, so it works the same way from any environment where the
139
+ package is installed:
140
+
141
+ ```console
142
+ exobrain-db-migrate current # Show applied revision(s)
143
+ exobrain-db-migrate history # List migration history
144
+ exobrain-db-migrate upgrade head # Apply all pending migrations
145
+ exobrain-db-migrate downgrade -1 # Roll back one migration
146
+ exobrain-db-migrate -x schema=org_42 current # Target a single organization schema
147
+ ```
148
+
149
+ It requires the same `SQL_*` environment variables as above, and writes its logs to `stdout` so they are
150
+ picked up by container log collectors. It is a thin wrapper: any other native Alembic command
151
+ (`stamp`, `heads`, `show`, `-c`/`ALEMBIC_CONFIG` override, ...) works unchanged.
152
+
137
153
  ---
138
154
 
139
155
  ## Project Structure
@@ -142,23 +158,26 @@ The source code lives under `src/exobrain/database/` as a namespace package:
142
158
 
143
159
  ```
144
160
  src/exobrain/database/
145
- ├── migrations/ # Alembic migration engine
146
- │ ├── alembic.ini # Alembic configuration file
147
- │ ├── env.py # Migration environment setup
148
- │ ├── migration_manager.py # Public API: upgrade / downgrade per org schema
149
- │ └── versions/ # Auto-generated migration scripts
150
- ├── model/ # SQLAlchemy ORM models
151
- │ ├── base.py # Declarative base classes
152
- │ ├── associations/ # Many-to-many association tables
153
- │ ├── enums/ # Database enumeration types (config, currency, running states)
154
- │ ├── general/ # Cross-organization models (copilots, permissions, roles,
155
- │ │ # predefined actions/executions/risks, reasons)
156
- │ └── org/ # Per-organization models (config, connections, dashboards,
157
- │ # running actions/executions/risks, scopes, users)
158
- └── tools/ # Reusable database utilities
159
- ├── jsonb_filter.py # Helper for filtering on JSONB columns
160
- ├── record_count.py # Efficient record counting queries
161
- └── sql_query_logger.py # SQLAlchemy query logging utility
161
+ ├── migrations/ # Alembic migration engine
162
+ │ ├── alembic.ini # Alembic configuration file
163
+ │ ├── cli.py # `exobrain-db-migrate` console script entry point
164
+ │ ├── env.py # Migration environment setup
165
+ │ ├── migration_manager.py # Public API: upgrade / downgrade per org schema
166
+ │ └── versions/ # Auto-generated migration scripts
167
+ ├── model/ # SQLAlchemy ORM models
168
+ │ ├── base.py # Declarative base classes
169
+ │ ├── associations/ # Many-to-many association tables
170
+ │ ├── enums/ # Database enumeration types (config, currency, running states)
171
+ │ ├── general/ # Cross-organization models (copilots, permissions, roles,
172
+ │ │ # predefined actions/executions/risks, reasons)
173
+ │ └── org/ # Per-organization models (config, connections, dashboards,
174
+ │ # running actions/executions/risks, scopes, users)
175
+ └── tools/ # Reusable database utilities
176
+ ├── jsonb_filter.py # Helper for filtering on JSONB columns
177
+ ├── record_count.py # Efficient record counting queries
178
+ ├── report_field_coercion.py # Coerce raw context values into typed report slots
179
+ ├── risk_report_projector.py # Project declared reporting fields into risk_report_fact
180
+ └── sql_query_logger.py # SQLAlchemy query logging utility
162
181
  ```
163
182
 
164
183
  ### Key design decisions
@@ -102,6 +102,29 @@ For creating a new migration, pass `-c` explicitly so the file naming template f
102
102
  alembic -c src/exobrain/database/migrations/alembic.ini revision --autogenerate -m "short description"
103
103
  ```
104
104
 
105
+ #### Running migrations from outside this repository
106
+
107
+ The `alembic` CLI above only works from this project's root, since it relies on the `[tool.alembic]`
108
+ section of this repo's `pyproject.toml`. Consuming projects (e.g. `exobrain-server`) or containers that
109
+ only have `exobrain-database` installed as a dependency don't have that file, and the packaged
110
+ `alembic.ini` sits inside the installed package (e.g.: under `.venv/`), which is impractical to locate.
111
+
112
+ For that case, `exobrain-database` ships a console script, `exobrain-db-migrate`, that resolves its own
113
+ `alembic.ini` and wraps the full Alembic CLI, so it works the same way from any environment where the
114
+ package is installed:
115
+
116
+ ```console
117
+ exobrain-db-migrate current # Show applied revision(s)
118
+ exobrain-db-migrate history # List migration history
119
+ exobrain-db-migrate upgrade head # Apply all pending migrations
120
+ exobrain-db-migrate downgrade -1 # Roll back one migration
121
+ exobrain-db-migrate -x schema=org_42 current # Target a single organization schema
122
+ ```
123
+
124
+ It requires the same `SQL_*` environment variables as above, and writes its logs to `stdout` so they are
125
+ picked up by container log collectors. It is a thin wrapper: any other native Alembic command
126
+ (`stamp`, `heads`, `show`, `-c`/`ALEMBIC_CONFIG` override, ...) works unchanged.
127
+
105
128
  ---
106
129
 
107
130
  ## Project Structure
@@ -110,23 +133,26 @@ The source code lives under `src/exobrain/database/` as a namespace package:
110
133
 
111
134
  ```
112
135
  src/exobrain/database/
113
- ├── migrations/ # Alembic migration engine
114
- │ ├── alembic.ini # Alembic configuration file
115
- │ ├── env.py # Migration environment setup
116
- │ ├── migration_manager.py # Public API: upgrade / downgrade per org schema
117
- │ └── versions/ # Auto-generated migration scripts
118
- ├── model/ # SQLAlchemy ORM models
119
- │ ├── base.py # Declarative base classes
120
- │ ├── associations/ # Many-to-many association tables
121
- │ ├── enums/ # Database enumeration types (config, currency, running states)
122
- │ ├── general/ # Cross-organization models (copilots, permissions, roles,
123
- │ │ # predefined actions/executions/risks, reasons)
124
- │ └── org/ # Per-organization models (config, connections, dashboards,
125
- │ # running actions/executions/risks, scopes, users)
126
- └── tools/ # Reusable database utilities
127
- ├── jsonb_filter.py # Helper for filtering on JSONB columns
128
- ├── record_count.py # Efficient record counting queries
129
- └── sql_query_logger.py # SQLAlchemy query logging utility
136
+ ├── migrations/ # Alembic migration engine
137
+ │ ├── alembic.ini # Alembic configuration file
138
+ │ ├── cli.py # `exobrain-db-migrate` console script entry point
139
+ │ ├── env.py # Migration environment setup
140
+ │ ├── migration_manager.py # Public API: upgrade / downgrade per org schema
141
+ │ └── versions/ # Auto-generated migration scripts
142
+ ├── model/ # SQLAlchemy ORM models
143
+ │ ├── base.py # Declarative base classes
144
+ │ ├── associations/ # Many-to-many association tables
145
+ │ ├── enums/ # Database enumeration types (config, currency, running states)
146
+ │ ├── general/ # Cross-organization models (copilots, permissions, roles,
147
+ │ │ # predefined actions/executions/risks, reasons)
148
+ │ └── org/ # Per-organization models (config, connections, dashboards,
149
+ │ # running actions/executions/risks, scopes, users)
150
+ └── tools/ # Reusable database utilities
151
+ ├── jsonb_filter.py # Helper for filtering on JSONB columns
152
+ ├── record_count.py # Efficient record counting queries
153
+ ├── report_field_coercion.py # Coerce raw context values into typed report slots
154
+ ├── risk_report_projector.py # Project declared reporting fields into risk_report_fact
155
+ └── sql_query_logger.py # SQLAlchemy query logging utility
130
156
  ```
131
157
 
132
158
  ### Key design decisions
@@ -0,0 +1,113 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.23,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "exobrain-database"
7
+ version = "0.3.0"
8
+ description = "Exobrain database model and migration management"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license-files = ["LICENSE.md"]
12
+ keywords = []
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Programming Language :: Python",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Topic :: Software Development :: Libraries",
20
+ "Topic :: Database",
21
+ "Topic :: Database :: Database Engines/Servers",
22
+ ]
23
+ dependencies = [
24
+ "alembic>=1.18.4",
25
+ "psycopg[binary]>=3.3.4",
26
+ "sqlalchemy>=2.0.51",
27
+ ]
28
+
29
+ [[project.authors]]
30
+ name = "Laurent LAPORTE"
31
+ email = "laurent@dfya.io"
32
+
33
+ [project.urls]
34
+ Documentation = "https://github.com/MyExobrain/exobrain-database#readme"
35
+ Issues = "https://github.com/MyExobrain/exobrain-database/issues"
36
+ Source = "https://github.com/MyExobrain/exobrain-database"
37
+
38
+ [project.scripts]
39
+ exobrain-db-migrate = "exobrain.database.migrations.cli:main"
40
+
41
+ [dependency-groups]
42
+ dev = [
43
+ "coverage>=7.14.2",
44
+ "mkdocs>=1.6.1",
45
+ "mkdocs-material>=9.6.0",
46
+ "mypy>=2.1.0",
47
+ "pytest>=9.1.1",
48
+ "pytest-cov>=7.1.0",
49
+ "twine>=6.2.0",
50
+ ]
51
+
52
+ [tool.uv.build-backend]
53
+ module-name = "exobrain.database"
54
+
55
+ [tool.coverage.run]
56
+ source_pkgs = [
57
+ "exobrain.database",
58
+ "tests",
59
+ ]
60
+ branch = true
61
+ parallel = true
62
+
63
+ [tool.coverage.paths]
64
+ exobrain_database_model = [
65
+ "src/exobrain/database",
66
+ "*/exobrain-database/src/exobrain/database",
67
+ ]
68
+ tests = [
69
+ "tests",
70
+ "*/exobrain-database/tests",
71
+ ]
72
+
73
+ [tool.coverage.report]
74
+ exclude_lines = [
75
+ "no cov",
76
+ "if __name__ == .__main__.:",
77
+ "if TYPE_CHECKING:",
78
+ ]
79
+
80
+ [tool.mypy]
81
+ python_version = "3.13"
82
+ namespace_packages = true
83
+ explicit_package_bases = true
84
+ mypy_path = "src"
85
+ ignore_missing_imports = true
86
+ strict = true
87
+ exclude = ["src/exobrain/database/migrations/versions"]
88
+
89
+ [tool.ruff]
90
+ line-length = 120
91
+ indent-width = 4
92
+ target-version = "py312"
93
+ exclude = ["src/exobrain/database/migrations/versions"]
94
+
95
+ [tool.ruff.lint.extend-per-file-ignores]
96
+ "src/exobrain/database/model/*/*.py" = ["TID252"]
97
+ "src/exobrain/database/tools/*.py" = ["TID252"]
98
+ "src/exobrain/database/migrations/versions/*.py" = ["INP001"]
99
+
100
+ [tool.alembic]
101
+ script_location = "src/exobrain/database/migrations"
102
+
103
+ [tool.ty.rules]
104
+ all = "error"
105
+ missing-override-decorator = "ignore"
106
+ unsound-assignment = "ignore"
107
+ unsound-return-statement = "ignore"
108
+
109
+ [tool.ty.src]
110
+ exclude = ["src/exobrain/database/migrations/versions"]
111
+
112
+ [tool.ty.environment]
113
+ python-version = "3.12"
@@ -1,17 +1,17 @@
1
1
  [build-system]
2
- requires = ["uv_build>=0.11.23,<0.12"]
2
+ requires = ["uv_build>=0.11.23,<0.13"]
3
3
  build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "exobrain-database"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "Exobrain database model and migration management"
9
9
  authors = [
10
10
  { name = "Laurent LAPORTE", email = "laurent@dfya.io" }
11
11
  ]
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.12"
14
- license = { file = "LICENSE.md" }
14
+ license-files = ["LICENSE.md"]
15
15
  keywords = []
16
16
  classifiers = [
17
17
  "Development Status :: 4 - Beta",
@@ -22,7 +22,6 @@ classifiers = [
22
22
  "Topic :: Software Development :: Libraries",
23
23
  "Topic :: Database",
24
24
  "Topic :: Database :: Database Engines/Servers",
25
- "License :: Other/Proprietary License",
26
25
  ]
27
26
  dependencies = [
28
27
  "alembic>=1.18.4",
@@ -35,9 +34,14 @@ Documentation = "https://github.com/MyExobrain/exobrain-database#readme"
35
34
  Issues = "https://github.com/MyExobrain/exobrain-database/issues"
36
35
  Source = "https://github.com/MyExobrain/exobrain-database"
37
36
 
37
+ [project.scripts]
38
+ exobrain-db-migrate = "exobrain.database.migrations.cli:main"
39
+
38
40
  [dependency-groups]
39
41
  dev = [
40
42
  "coverage>=7.14.2",
43
+ "mkdocs>=1.6.1",
44
+ "mkdocs-material>=9.6.0",
41
45
  "mypy>=2.1.0",
42
46
  "pytest>=9.1.1",
43
47
  "pytest-cov>=7.1.0",
@@ -100,6 +104,7 @@ exclude = [
100
104
 
101
105
  [tool.ruff.lint.extend-per-file-ignores]
102
106
  "src/exobrain/database/model/*/*.py" = ["TID252"]
107
+ "src/exobrain/database/tools/*.py" = ["TID252"]
103
108
  "src/exobrain/database/migrations/versions/*.py" = ["INP001"]
104
109
 
105
110
 
@@ -119,6 +124,13 @@ script_location = "src/exobrain/database/migrations"
119
124
  [tool.ty.rules]
120
125
  all = "error"
121
126
  missing-override-decorator = "ignore"
127
+ # SQLAlchemy's `mapped_column()` and `relationship()` return descriptor types (`MappedColumn[Any]`,
128
+ # `_RelationshipDeclared[Any]`) that ty cannot narrow to the declared `Mapped[...]` annotation.
129
+ # Every model attribute of the package trips this, 317 times, with nothing actionable to change:
130
+ # the annotation is the documented SQLAlchemy 2.0 style and mypy --strict accepts it. Re-enable
131
+ # once ty understands the SQLAlchemy declarative plugin.
132
+ unsound-assignment = "ignore"
133
+ unsound-return-statement = "ignore"
122
134
 
123
135
  [tool.ty.src]
124
136
  exclude = [
@@ -6,4 +6,4 @@ from exobrain.database.migrations.migration_manager import (
6
6
  upgrade,
7
7
  )
8
8
 
9
- __all__ = ["configure", "upgrade", "downgrade"]
9
+ __all__ = ["configure", "downgrade", "upgrade"]
@@ -95,7 +95,7 @@ qualname = alembic
95
95
 
96
96
  [handler_console]
97
97
  class = StreamHandler
98
- args = (sys.stderr,)
98
+ args = (sys.stdout,)
99
99
  level = NOTSET
100
100
  formatter = generic
101
101
 
@@ -0,0 +1,72 @@
1
+ """
2
+ Command-line entry point for Alembic migrations, packaged with ``exobrain-database``.
3
+
4
+ The Alembic configuration file (``alembic.ini``) lives inside the installed
5
+ package, which makes it inconvenient to locate from a consuming project
6
+ (e.g. ``exobrain-server``) or from a container where the virtual environment
7
+ layout is not known in advance.
8
+
9
+ This module exposes a ``main()`` function, wired to the ``exobrain-db-migrate``
10
+ console script (see ``pyproject.toml``), which resolves ``alembic.ini``
11
+ relative to this module and delegates to Alembic's own command-line parser.
12
+ Every native Alembic command is therefore available unchanged, in particular
13
+ the ones needed for routine maintenance and diagnostics in a containerized
14
+ environment:
15
+
16
+ - ``exobrain-db-migrate current`` show the current revision(s)
17
+ - ``exobrain-db-migrate history`` list the migration history
18
+ - ``exobrain-db-migrate upgrade head`` apply pending migrations
19
+ - ``exobrain-db-migrate downgrade -1`` roll back one migration
20
+ - ``exobrain-db-migrate heads`` / ``show <rev>`` / ``stamp <rev>`` / ...
21
+ - ``exobrain-db-migrate -x schema=org_<id> current`` target a single org schema
22
+
23
+ Usage from anywhere, once ``exobrain-database`` is installed in the active
24
+ virtual environment::
25
+
26
+ exobrain-db-migrate upgrade head
27
+ exobrain-db-migrate -x schema=org_42 current
28
+
29
+ The database connection is read by ``env.py`` from the ``SQL_*`` environment
30
+ variables (``SQL_ENGINE``, ``SQL_HOST``, ``SQL_DATABASE``, ``SQL_USER``,
31
+ ``SQL_PORT``, ``SQL_PASSWORD``), which must be set in the calling environment
32
+ (e.g.: injected into the container). Log output is written to ``stdout`` (see
33
+ the ``[handler_console]`` section of ``alembic.ini``), so it is captured by
34
+ container log collectors alongside the application's own logs.
35
+ """
36
+
37
+ import os
38
+ import sys
39
+ from collections.abc import Sequence
40
+ from pathlib import Path
41
+
42
+ from alembic.config import main as _alembic_main
43
+
44
+ HERE = Path(__file__).parent
45
+ DEFAULT_ALEMBIC_INI = HERE / "alembic.ini"
46
+
47
+
48
+ def main(argv: Sequence[str] | None = None) -> None:
49
+ """
50
+ Entry point for the ``exobrain-db-migrate`` console script.
51
+
52
+ Resolves the packaged ``alembic.ini`` and forwards all arguments to
53
+ Alembic's own command-line interface, so every native Alembic command
54
+ and option is supported unchanged.
55
+
56
+ An already-set ``ALEMBIC_CONFIG`` environment variable, or an explicit
57
+ ``-c``/``--config`` argument, takes precedence over the packaged
58
+ default, so callers can still point to a different configuration file
59
+ if needed.
60
+
61
+ Args:
62
+ argv: Command-line arguments to parse, excluding the program name.
63
+ Defaults to ``sys.argv[1:]``.
64
+ """
65
+ # noinspection PyUnresolvedReferences
66
+ argv = argv if argv is not None else sys.argv[1:]
67
+ os.environ.setdefault("ALEMBIC_CONFIG", str(DEFAULT_ALEMBIC_INI))
68
+ _alembic_main(argv=argv, prog="exobrain-db-migrate")
69
+
70
+
71
+ if __name__ == "__main__": # pragma: no cover
72
+ main()
@@ -6,6 +6,7 @@ from logging.config import fileConfig
6
6
  from alembic import context
7
7
  from alembic.runtime.environment import NameFilterType
8
8
  from sqlalchemy import URL, Connection, Engine, Result, Table, column, create_engine, select, table
9
+ from sqlalchemy.pool import NullPool
9
10
  from sqlalchemy.schema import CreateSchema
10
11
  from sqlalchemy.sql import text
11
12
  from sqlalchemy.sql.schema import SchemaItem
@@ -60,16 +61,16 @@ def has_autogenerate() -> bool:
60
61
  """
61
62
  commands = _get_alembic_commands()
62
63
  is_upgrade = len(commands) > 0 and callable(commands[0]) and commands[0].__name__ == "upgrade"
63
- is_autogenerate = len(commands) > 2 and "autogenerate" in commands[2] # noqa PLR2004
64
+ is_autogenerate = len(commands) > 2 and "autogenerate" in commands[2]
64
65
  return is_upgrade or is_autogenerate
65
66
 
66
67
 
67
68
  def is_public(
68
69
  schema_item: SchemaItem,
69
- name: str | None, # noqa
70
+ name: str | None,
70
71
  type_: NameFilterType,
71
- reflected: bool, # noqa
72
- compare_to: SchemaItem | None, # noqa
72
+ reflected: bool,
73
+ compare_to: SchemaItem | None,
73
74
  ) -> bool:
74
75
  if type_ == "table" and schema_item.info.get("skip_autogenerate"):
75
76
  return False
@@ -89,7 +90,7 @@ def is_org(
89
90
  schema_item: SchemaItem,
90
91
  name: str | None,
91
92
  type_: NameFilterType,
92
- reflected: bool, # noqa
93
+ reflected: bool,
93
94
  compare_to: SchemaItem | None,
94
95
  ) -> bool:
95
96
  if type_ == "table" and schema_item.info.get("skip_autogenerate"):
@@ -111,8 +112,8 @@ def run_base_migrations_online(connection: Connection) -> None:
111
112
  connection=connection,
112
113
  target_metadata=base_metadata,
113
114
  include_object=is_public,
114
- upgrade_token="base_up", # noqa: S106
115
- downgrade_token="base_down", # noqa: S106
115
+ upgrade_token="base_up",
116
+ downgrade_token="base_down",
116
117
  compare_type=True,
117
118
  )
118
119
 
@@ -144,8 +145,8 @@ def run_orgs_migrations_online(connection: Connection) -> None:
144
145
  connection=connection,
145
146
  target_metadata=base_metadata,
146
147
  include_object=is_org,
147
- upgrade_token="org_up", # noqa: S106
148
- downgrade_token="org_down", # noqa: S106
148
+ upgrade_token="org_up",
149
+ downgrade_token="org_down",
149
150
  compare_type=True,
150
151
  )
151
152
 
@@ -181,20 +182,26 @@ def run_migrations_online() -> None:
181
182
  port=sql_port,
182
183
  database=sql_database,
183
184
  )
184
- db_engine: Engine = create_engine(db_url)
185
-
186
- with db_engine.connect() as connection:
187
- # If the first argument is a function, and it is a downgrade, we reverse the order of migrations
188
- # to ensure that base migrations are applied before organization migrations.
189
- commands = _get_alembic_commands()
190
- is_downgrade = len(commands) > 0 and callable(commands[0]) and commands[0].__name__ == "downgrade"
191
- if is_downgrade:
192
- run_orgs_migrations_online(connection)
193
- run_base_migrations_online(connection)
194
- else:
195
- run_base_migrations_online(connection)
196
- run_orgs_migrations_online(connection)
197
- connection.commit()
185
+ # A migration needs a single connection: ``NullPool`` closes it as soon as it is released,
186
+ # and ``dispose()`` frees the engine even when a migration fails. Without them, every Alembic
187
+ # command run in the same process (e.g. ``migration_manager.upgrade()`` for each organization)
188
+ # left a connection open, until PostgreSQL refused new clients (EXO-1800).
189
+ db_engine: Engine = create_engine(db_url, poolclass=NullPool)
190
+ try:
191
+ with db_engine.connect() as connection:
192
+ # If the first argument is a function, and it is a downgrade, we reverse the order of migrations
193
+ # to ensure that base migrations are applied before organization migrations.
194
+ commands = _get_alembic_commands()
195
+ is_downgrade = len(commands) > 0 and callable(commands[0]) and commands[0].__name__ == "downgrade"
196
+ if is_downgrade:
197
+ run_orgs_migrations_online(connection)
198
+ run_base_migrations_online(connection)
199
+ else:
200
+ run_base_migrations_online(connection)
201
+ run_orgs_migrations_online(connection)
202
+ connection.commit()
203
+ finally:
204
+ db_engine.dispose()
198
205
 
199
206
 
200
207
  run_migrations_online()
@@ -106,4 +106,8 @@ def downgrade(org_id: UUID | int | str) -> None:
106
106
  TypeError: If org_id is not a valid type (UUID, int, or numeric string).
107
107
  """
108
108
  config = configure(org_id)
109
- command.downgrade(config, "head")
109
+ # "base", not "head": "head" is a no-op (the schema is already there), which silently skips
110
+ # every downgrade step -- e.g. it leaves running_risk/running_action/running_execution.status
111
+ # as their Postgres enum types instead of reverting them to TEXT, which then breaks servers
112
+ # rolled back to a pre-enum release (they query with a ::VARCHAR cast the enum type rejects).
113
+ command.downgrade(config, "base")
@@ -1,7 +1,9 @@
1
1
  """Add running_action_summary table with TEXT column
2
+
2
3
  Revision ID: 8f3c5e2d9a1b
3
4
  Revises: 881f104f8b2b
4
5
  Create Date: 2026-04-20 10:15:00.000000+00:00
6
+
5
7
  """
6
8
 
7
9
  from collections.abc import Sequence
@@ -1,7 +1,7 @@
1
1
  """Add kpi_names to predefined_action
2
2
 
3
3
  Revision ID: c3e8047f29f6
4
- Revises: 881f104f8b2b
4
+ Revises: 8f3c5e2d9a1b
5
5
  Create Date: 2026-04-30 13:57:03.686180+00:00
6
6
 
7
7
  """