matrx-orm 3.1.10__tar.gz → 3.1.11__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 (275) hide show
  1. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/PKG-INFO +1 -1
  2. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/__init__.py +8 -2
  3. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/query/executor.py +6 -0
  4. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/__init__.py +8 -2
  5. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/errors.py +3 -1
  6. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/managed.py +77 -37
  7. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/session.py +6 -0
  8. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/pyproject.toml +1 -1
  9. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_managed_write_guard.py +78 -9
  10. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/.gitignore +0 -0
  11. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/BASE_CLASS_METHODS.md +0 -0
  12. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/CLAUDE.md +0 -0
  13. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/MODEL_API.md +0 -0
  14. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/README.md +0 -0
  15. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/database/orm/extended/managers/ai_model_base.py +0 -0
  16. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/docs/migrations.md +0 -0
  17. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/MODULE_README.md +0 -0
  18. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/adapters/MODULE_README.md +0 -0
  19. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/adapters/__init__.py +0 -0
  20. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/adapters/async_postgresql.py +0 -0
  21. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/adapters/base_adapter.py +0 -0
  22. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/adapters/postgresql.py +0 -0
  23. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
  24. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/adapters/supabase_adapter.py +0 -0
  25. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/admin/__init__.py +0 -0
  26. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/admin/router.py +0 -0
  27. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/api/__init__.py +0 -0
  28. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/api/auth.py +0 -0
  29. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/api/config.py +0 -0
  30. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/api/handlers.py +0 -0
  31. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/api/protocol.py +0 -0
  32. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/api/server.py +0 -0
  33. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/associations.py +0 -0
  34. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/cache_debug.py +0 -0
  35. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/client/MODULE_README.md +0 -0
  36. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/client/__init__.py +0 -0
  37. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/client/postgres_connection.py +0 -0
  38. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/client/postgrest.py +0 -0
  39. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/client/supabase_auth.py +0 -0
  40. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/client/supabase_config.py +0 -0
  41. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/client/supabase_manager.py +0 -0
  42. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/EXTENDED-TASK.md +0 -0
  43. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/MODULE_README.md +0 -0
  44. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
  45. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/TASKS.md +0 -0
  46. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/__init__.py +0 -0
  47. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/async_db_manager.py +0 -0
  48. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/base.py +0 -0
  49. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/config.py +0 -0
  50. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/db_function.py +0 -0
  51. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/diagnostics.py +0 -0
  52. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/expressions.py +0 -0
  53. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/extended.py +0 -0
  54. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/fields.py +0 -0
  55. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/introspection.py +0 -0
  56. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/listen.py +0 -0
  57. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/loop_filters.py +0 -0
  58. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/model_dto.py +0 -0
  59. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/model_view.py +0 -0
  60. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/paginator.py +0 -0
  61. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/pydantic_bridge.py +0 -0
  62. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/registry.py +0 -0
  63. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/relations.py +0 -0
  64. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/resilience.py +0 -0
  65. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/rls_session.py +0 -0
  66. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/signals.py +0 -0
  67. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/transaction.py +0 -0
  68. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/types.py +0 -0
  69. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/core/write_queue.py +0 -0
  70. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/entity.py +0 -0
  71. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/error_handling.py +0 -0
  72. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/exceptions.py +0 -0
  73. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/extended/__init__.py +0 -0
  74. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/extended/app_error_handler.py +0 -0
  75. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/middleware/__init__.py +0 -0
  76. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/middleware/base.py +0 -0
  77. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/MODULE_README.md +0 -0
  78. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/__init__.py +0 -0
  79. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/cli.py +0 -0
  80. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/ddl.py +0 -0
  81. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/diff.py +0 -0
  82. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/executor.py +0 -0
  83. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/integration.py +0 -0
  84. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/loader.py +0 -0
  85. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/operations.py +0 -0
  86. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/state.py +0 -0
  87. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/migrations/table_filter.py +0 -0
  88. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/MODULE_README.md +0 -0
  89. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/__init__.py +0 -0
  90. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/bulk_update_values.py +0 -0
  91. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/conflict.py +0 -0
  92. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/conflict_writes.py +0 -0
  93. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/create.py +0 -0
  94. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/delete.py +0 -0
  95. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/dynamic_admin.py +0 -0
  96. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/queue_claim.py +0 -0
  97. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/read.py +0 -0
  98. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/staging_load.py +0 -0
  99. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/operations/update.py +0 -0
  100. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/py.typed +0 -0
  101. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/python_sql/MODULE_README.md +0 -0
  102. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/python_sql/__init__.py +0 -0
  103. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/python_sql/db_objects.py +0 -0
  104. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
  105. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  106. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/query/MODULE_README.md +0 -0
  107. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/query/__init__.py +0 -0
  108. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/query/builder.py +0 -0
  109. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/MODULE_README.md +0 -0
  110. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/__init__.py +0 -0
  111. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/code_handler.py +0 -0
  112. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/codegen_writer.py +0 -0
  113. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/columns.py +0 -0
  114. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/common.py +0 -0
  115. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/diff_preview.py +0 -0
  116. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
  117. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/generator.py +0 -0
  118. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  119. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  120. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  121. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
  122. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/package_wiring.py +0 -0
  123. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/relationships.py +0 -0
  124. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/runner.py +0 -0
  125. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/schema.py +0 -0
  126. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/schema_manager.py +0 -0
  127. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/tables.py +0 -0
  128. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/schema_builder/views.py +0 -0
  129. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/README.md +0 -0
  130. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/coalesce.py +0 -0
  131. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/dag.py +0 -0
  132. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/fallback.py +0 -0
  133. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/flush.py +0 -0
  134. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/lifecycle.py +0 -0
  135. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/op.py +0 -0
  136. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/reads.py +0 -0
  137. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/session/telemetry.py +0 -0
  138. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/sql_executor/MODULE_README.md +0 -0
  139. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/sql_executor/__init__.py +0 -0
  140. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/sql_executor/executor.py +0 -0
  141. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/sql_executor/queries.py +0 -0
  142. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/sql_executor/registry.py +0 -0
  143. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/sql_executor/types.py +0 -0
  144. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/sql_executor/utils.py +0 -0
  145. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/state.py +0 -0
  146. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/utils/__init__.py +0 -0
  147. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/utils/sql_utils.py +0 -0
  148. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/matrx_orm/utils/type_converters.py +0 -0
  149. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/scripts/git-branches.sh +0 -0
  150. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/scripts/publish.sh +0 -0
  151. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/scripts/release.sh +0 -0
  152. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/MODULE_README.md +0 -0
  153. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/__init__.py +0 -0
  154. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/conftest.py +0 -0
  155. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/MODULE_README.md +0 -0
  156. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/__init__.py +0 -0
  157. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_admin_db_columns.py +0 -0
  158. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_admin_search_sentinels.py +0 -0
  159. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_advisory_lock.py +0 -0
  160. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_agent_message.py +0 -0
  161. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_api_auth.py +0 -0
  162. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_api_config.py +0 -0
  163. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_api_handlers.py +0 -0
  164. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_api_protocol.py +0 -0
  165. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_array_agg_order_by.py +0 -0
  166. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_associations.py +0 -0
  167. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_bulk_update_by_pk.py +0 -0
  168. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
  169. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_cache_debug.py +0 -0
  170. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_call_function.py +0 -0
  171. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_case_when.py +0 -0
  172. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_composite_pk_filter.py +0 -0
  173. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_composite_pk_write_paths.py +0 -0
  174. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_config.py +0 -0
  175. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_conflict_target.py +0 -0
  176. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_conflict_writes.py +0 -0
  177. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_connection_codecs.py +0 -0
  178. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_connection_poison_guard.py +0 -0
  179. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_count_composite_distinct.py +0 -0
  180. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_db_function_field.py +0 -0
  181. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_ddl_generator.py +0 -0
  182. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_dirty_tracking.py +0 -0
  183. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_exceptions.py +0 -0
  184. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_execute_admin_sql.py +0 -0
  185. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_expression_primitives.py +0 -0
  186. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_fields.py +0 -0
  187. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
  188. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_filter_raw.py +0 -0
  189. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_from_alias.py +0 -0
  190. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_fts.py +0 -0
  191. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_func_expression_args.py +0 -0
  192. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_having_annotate_alias.py +0 -0
  193. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
  194. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_introspect_rls_policies.py +0 -0
  195. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_join_and_aggregate.py +0 -0
  196. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_listen_notify.py +0 -0
  197. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_matrx_entity.py +0 -0
  198. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_migration_diff_types.py +0 -0
  199. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_migration_loader.py +0 -0
  200. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_model_instance.py +0 -0
  201. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_model_meta.py +0 -0
  202. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_order_by_expression.py +0 -0
  203. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_patch_jsonb_path.py +0 -0
  204. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_postgrest_filters.py +0 -0
  205. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_query_builder.py +0 -0
  206. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_query_error_detail.py +0 -0
  207. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_query_executor_sql.py +0 -0
  208. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_query_timeout.py +0 -0
  209. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
  210. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_queue_claim.py +0 -0
  211. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_registry.py +0 -0
  212. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_registry_multi_database.py +0 -0
  213. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_registry_multi_schema.py +0 -0
  214. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_relations.py +0 -0
  215. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_resilience.py +0 -0
  216. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_schema_exists.py +0 -0
  217. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_session_advisory_lock.py +0 -0
  218. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_state_cache.py +0 -0
  219. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_subquery_filter_raw.py +0 -0
  220. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_subquery_in_filter.py +0 -0
  221. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_supabase_auth.py +0 -0
  222. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_supabase_config.py +0 -0
  223. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_update_case_expression.py +0 -0
  224. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_update_subquery.py +0 -0
  225. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_upsert_with_conflict.py +0 -0
  226. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_values_jsonb_decode.py +0 -0
  227. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_watched_lifecycle.py +0 -0
  228. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level1/test_write_retry_semantics.py +0 -0
  229. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/MODULE_README.md +0 -0
  230. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/__init__.py +0 -0
  231. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/conftest.py +0 -0
  232. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_bulk_ops.py +0 -0
  233. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_cache_integration.py +0 -0
  234. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_crud.py +0 -0
  235. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_foreign_keys.py +0 -0
  236. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_m2m.py +0 -0
  237. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_manager.py +0 -0
  238. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_migrations_live.py +0 -0
  239. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_query_execution.py +0 -0
  240. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/level2/test_schema_diff.py +0 -0
  241. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project/.env.example +0 -0
  242. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project/README.md +0 -0
  243. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project/__init__.py +0 -0
  244. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project/generate.py +0 -0
  245. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project/generated/.gitkeep +0 -0
  246. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project/matrx_orm.yaml +0 -0
  247. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project/test_schema_generation.py +0 -0
  248. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project_desktop/.env.example +0 -0
  249. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project_desktop/README.md +0 -0
  250. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project_desktop/__init__.py +0 -0
  251. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project_desktop/client_example.py +0 -0
  252. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project_desktop/client_example.ts +0 -0
  253. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project_desktop/client_supabase_example.py +0 -0
  254. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/sample_project_desktop/server.py +0 -0
  255. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/schema/entity_tests.py +0 -0
  256. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/schema/test_base_generation.py +0 -0
  257. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/schema/test_composite_pk_fk_generation.py +0 -0
  258. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/schema/test_generate_schema.py +0 -0
  259. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/schema/test_multi_schema_output.py +0 -0
  260. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/__init__.py +0 -0
  261. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/conftest.py +0 -0
  262. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_capture_poison_proof.py +0 -0
  263. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_coalesce.py +0 -0
  264. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_dag.py +0 -0
  265. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_disk_spill_fallback.py +0 -0
  266. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_flush_individual_fallback.py +0 -0
  267. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_governed_write.py +0 -0
  268. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_managed.py +0 -0
  269. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_op_enqueue_site.py +0 -0
  270. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_reads.py +0 -0
  271. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/session/test_session.py +0 -0
  272. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/test_database_name_alias.py +0 -0
  273. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/test_model_cls_refactor.py +0 -0
  274. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/test_sql_param_casts.py +0 -0
  275. {matrx_orm-3.1.10 → matrx_orm-3.1.11}/tests/test_sync_twins_guard.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrx-orm
3
- Version: 3.1.10
3
+ Version: 3.1.11
4
4
  Summary: Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching
5
5
  Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream-current
6
6
  Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream-current
@@ -282,13 +282,16 @@ from matrx_orm.session import (
282
282
  SessionPhase,
283
283
  WatchedLifecycleConfig,
284
284
  WatchedLifecycleRegistry,
285
- allow_direct_managed_write,
285
+ COORDINATOR_BYPASS_ACKNOWLEDGEMENT,
286
+ allow_direct_coordinator_write,
287
+ coordinator_policy_tables,
286
288
  current_session,
287
289
  declare_managed,
288
290
  drain_spilled_ops,
289
291
  is_in_session,
290
292
  record_error,
291
293
  record_failures,
294
+ register_coordinator_owned_model,
292
295
  )
293
296
  from matrx_orm.session import (
294
297
  run_sweeper as run_lifecycle_sweeper,
@@ -299,7 +302,10 @@ from matrx_orm.session import (
299
302
 
300
303
  __all__ = [
301
304
  "CoordinatorWriteViolation",
302
- "allow_direct_managed_write",
305
+ "COORDINATOR_BYPASS_ACKNOWLEDGEMENT",
306
+ "allow_direct_coordinator_write",
307
+ "coordinator_policy_tables",
308
+ "register_coordinator_owned_model",
303
309
  # ── Configuration ──────────────────────────────────────────────────────────
304
310
  "DatabaseProjectConfig",
305
311
  "register_database",
@@ -957,6 +957,12 @@ class QueryExecutor:
957
957
  (default ``BaseAdapter`` behaviour) so callers can fall through to the
958
958
  SQL path.
959
959
  """
960
+ from matrx_orm.session.managed import assert_model_write_allowed
961
+
962
+ assert_model_write_allowed(
963
+ self.model,
964
+ str(query.get("operation") or "adapter write"),
965
+ )
960
966
  return await self.db.execute_write_dict(query)
961
967
 
962
968
  async def insert(self, query: dict[str, Any]) -> dict[str, Any]:
@@ -67,9 +67,12 @@ from matrx_orm.session.lifecycle import (
67
67
  sweep_once,
68
68
  )
69
69
  from matrx_orm.session.managed import (
70
- allow_direct_managed_write,
70
+ COORDINATOR_BYPASS_ACKNOWLEDGEMENT,
71
+ allow_direct_coordinator_write,
72
+ coordinator_policy_tables,
71
73
  declare_managed,
72
74
  install_managed_writes,
75
+ register_coordinator_owned_model,
73
76
  )
74
77
  from matrx_orm.session.op import (
75
78
  OpType,
@@ -112,10 +115,13 @@ __all__ = [
112
115
  "coalesce_ops",
113
116
  "config_from_meta",
114
117
  "current_session",
115
- "allow_direct_managed_write",
118
+ "COORDINATOR_BYPASS_ACKNOWLEDGEMENT",
119
+ "allow_direct_coordinator_write",
120
+ "coordinator_policy_tables",
116
121
  "declare_managed",
117
122
  "has_pending_in_stack",
118
123
  "install_managed_writes",
124
+ "register_coordinator_owned_model",
119
125
  "is_in_session",
120
126
  "pending_ops_across_stack",
121
127
  "make_delete",
@@ -66,7 +66,9 @@ class CoordinatorWriteViolation(ManagedWriteViolation):
66
66
  f"Session scope is {actual_scope!r}. Queue this write through its "
67
67
  "Coordinator so parent and child rows share one transactional DAG. "
68
68
  "For a genuine out-of-request maintenance operation, use "
69
- "allow_direct_managed_write(model, reason='...') explicitly.",
69
+ "allow_direct_coordinator_write(model, reason='...', "
70
+ "acknowledgement="
71
+ "'YES_I_KNOW_I_AM_SKIPPING_THE_COORDINATOR_ON_PURPOSE') explicitly.",
70
72
  )
71
73
  self.model_name = model_name
72
74
  self.op_kind = op_kind
@@ -11,7 +11,7 @@ A Model opts into Session-aware writes by declaring
11
11
  # OR
12
12
  managed_writes = "strict" # raise ManagedWriteViolation if no Session
13
13
  # OR
14
- managed_writes = "coordinator" # require a named owner Session
14
+ managed_writes = "coordinator" # audit writes lacking owner authority
15
15
 
16
16
  When the Model's ``create`` / ``update`` / ``delete`` / ``bulk_*`` /
17
17
  ``upsert`` methods are called:
@@ -24,6 +24,9 @@ When the Model's ``create`` / ``update`` / ``delete`` / ``bulk_*`` /
24
24
  was a direct write.
25
25
  3. If NO active Session AND mode == ``"strict"``, raise
26
26
  :class:`ManagedWriteViolation` — loud red banner, full stack trace.
27
+ 4. Coordinator mode never blocks a write. A write without the Coordinator's
28
+ opaque authority (or an acknowledged exact-model override) continues and
29
+ emits a large red ERROR diagnostic. Authorized writes are silent.
27
30
 
28
31
  For backward compatibility, this layer activates only when
29
32
  ``managed_writes`` is truthy. Unmanaged Models keep their current
@@ -61,7 +64,6 @@ from matrx_utils import vcprint
61
64
 
62
65
  from matrx_orm.session.errors import (
63
66
  MANAGED_WRITE_SKILL_HINT,
64
- CoordinatorWriteViolation,
65
67
  ManagedWriteViolation,
66
68
  )
67
69
  from matrx_orm.session.session import Session, SessionPhase, session_stack
@@ -95,10 +97,16 @@ _STRICT_TABLES: set[str] = set()
95
97
  # merely opening a Session/transaction is not authority to write the table.
96
98
  _COORDINATOR_TABLES: dict[str, str] = {}
97
99
 
100
+ _COORDINATOR_AUTHORITY = object()
101
+
102
+ COORDINATOR_BYPASS_ACKNOWLEDGEMENT = (
103
+ "YES_I_KNOW_I_AM_SKIPPING_THE_COORDINATOR_ON_PURPOSE"
104
+ )
105
+
98
106
 
99
107
  @dataclass(frozen=True, slots=True)
100
108
  class DirectWriteException:
101
- model_name: str
109
+ model_cls: type
102
110
  reason: str
103
111
 
104
112
 
@@ -109,22 +117,23 @@ _direct_write_exceptions: ContextVar[tuple[DirectWriteException, ...]] = Context
109
117
 
110
118
 
111
119
  @contextmanager
112
- def allow_direct_managed_write(model_cls: type, *, reason: str) -> Iterator[None]:
113
- """Explicit, scoped escape hatch for coordinator-owned maintenance writes.
114
-
115
- ``reason`` is mandatory and appears in logs. This is intentionally not a
116
- boolean flag: exceptional code must state why it cannot use the owner.
117
- """
120
+ def allow_direct_coordinator_write(
121
+ model_cls: type,
122
+ *,
123
+ reason: str,
124
+ acknowledgement: str,
125
+ ) -> Iterator[None]:
126
+ """Temporarily acknowledge one model's intentional Coordinator bypass."""
118
127
  cleaned = reason.strip()
119
128
  if not cleaned:
120
- raise ValueError("allow_direct_managed_write requires a non-empty reason")
121
- exception = DirectWriteException(model_cls.__name__, cleaned)
129
+ raise ValueError("allow_direct_coordinator_write requires a non-empty reason")
130
+ if acknowledgement != COORDINATOR_BYPASS_ACKNOWLEDGEMENT:
131
+ raise ValueError(
132
+ "allow_direct_coordinator_write requires acknowledgement="
133
+ f"{COORDINATOR_BYPASS_ACKNOWLEDGEMENT!r}"
134
+ )
135
+ exception = DirectWriteException(model_cls, cleaned)
122
136
  token = _direct_write_exceptions.set(_direct_write_exceptions.get() + (exception,))
123
- logger.warning(
124
- "DIRECT WRITE EXCEPTION entered for %s: %s",
125
- model_cls.__name__,
126
- cleaned,
127
- )
128
137
  try:
129
138
  yield
130
139
  finally:
@@ -132,7 +141,22 @@ def allow_direct_managed_write(model_cls: type, *, reason: str) -> Iterator[None
132
141
 
133
142
 
134
143
  def _has_direct_exception(model_cls: type) -> bool:
135
- return any(item.model_name == model_cls.__name__ for item in _direct_write_exceptions.get())
144
+ return any(item.model_cls is model_cls for item in _direct_write_exceptions.get())
145
+
146
+
147
+ def _coordinator_session(*, database: str | None = None) -> Session:
148
+ """Create the Session capability reserved for matrx-ai's Coordinator."""
149
+ from matrx_orm.session.session import Session as SessionClass
150
+
151
+ return SessionClass(
152
+ database=database,
153
+ write_scope="coordinator",
154
+ _write_authority=_COORDINATOR_AUTHORITY,
155
+ )
156
+
157
+
158
+ def _has_coordinator_authority(session: Session | None) -> bool:
159
+ return session is not None and session._has_write_authority(_COORDINATOR_AUTHORITY)
136
160
 
137
161
  # Leading INSERT INTO / UPDATE / DELETE FROM target — ORM-generated SQL only.
138
162
  _WRITE_TARGET_RE = re.compile(
@@ -162,7 +186,20 @@ def _register_coordinator_table(model_cls: type, required_scope: str) -> None:
162
186
  getattr(meta, "table_name", None),
163
187
  ):
164
188
  if name:
165
- _COORDINATOR_TABLES[str(name).strip('"')] = required_scope
189
+ normalized = str(name).strip('"')
190
+ _COORDINATOR_TABLES[normalized] = required_scope
191
+ _STRICT_TABLES.discard(normalized)
192
+
193
+
194
+ def register_coordinator_owned_model(entry: Any) -> None:
195
+ """Host registrar consumed by matrx-ai's package-independent registry."""
196
+ model_cls = entry.model_cls
197
+ declare_managed(model_cls, mode="coordinator", write_scope="coordinator")
198
+
199
+
200
+ def coordinator_policy_tables() -> dict[str, str]:
201
+ """Return installed table policies for startup/release diagnostics."""
202
+ return dict(_COORDINATOR_TABLES)
166
203
 
167
204
 
168
205
  def _coordinator_scope_for_model(model_cls: type) -> str | None:
@@ -183,11 +220,11 @@ def assert_model_write_allowed(
183
220
  op_kind: str,
184
221
  *,
185
222
  session: Session | None = None,
186
- ) -> None:
187
- """Reject a coordinator-owned Model write without its owner Session."""
223
+ ) -> bool:
224
+ """Warn on a Coordinator-owned Model write without Coordinator authority."""
188
225
  required_scope = _coordinator_scope_for_model(model_cls)
189
226
  if required_scope is None or _has_direct_exception(model_cls):
190
- return
227
+ return True
191
228
  active = session
192
229
  if active is None:
193
230
  for candidate in reversed(session_stack()):
@@ -195,19 +232,14 @@ def assert_model_write_allowed(
195
232
  active = candidate
196
233
  break
197
234
  actual_scope = active.write_scope if active is not None else None
198
- if actual_scope == required_scope:
199
- return
235
+ if _has_coordinator_authority(active):
236
+ return True
200
237
  banner = _format_coordinator_banner(
201
238
  model_cls.__name__, op_kind, required_scope, actual_scope
202
239
  )
203
240
  vcprint(banner, color="red")
204
241
  logger.error("CoordinatorWriteViolation: %s", banner)
205
- raise CoordinatorWriteViolation(
206
- model_cls.__name__,
207
- op_kind,
208
- required_scope=required_scope,
209
- actual_scope=actual_scope,
210
- )
242
+ return False
211
243
 
212
244
 
213
245
  def _has_active_open_session() -> bool:
@@ -248,9 +280,11 @@ def assert_managed_write_allowed(query: str) -> None:
248
280
  else:
249
281
  actual = _active_write_scope()
250
282
  if actual != required_scope:
251
- raise CoordinatorWriteViolation(
252
- token, "write", required_scope=required_scope, actual_scope=actual
283
+ banner = _format_coordinator_banner(
284
+ token, "write", required_scope, actual
253
285
  )
286
+ vcprint(banner, color="red", log_level="ERROR")
287
+ logger.error("CoordinatorWriteViolation: %s", banner)
254
288
  return
255
289
  # Governed contexts — always allowed:
256
290
  if _has_active_open_session():
@@ -529,6 +563,7 @@ def _wrap_classmethod(model_cls: type, method_name: str, original: Any, mode: st
529
563
 
530
564
  @functools.wraps(original_func)
531
565
  async def wrapped(cls, *args, **kwargs):
566
+ active_mode = _managed_mode(cls) or mode
532
567
  # Reentrancy guard: when the flush executor calls bulk_create /
533
568
  # bulk_update / bulk_delete to actually write rows, those calls
534
569
  # must pass through unchanged. Without this check we'd recurse
@@ -552,7 +587,7 @@ def _wrap_classmethod(model_cls: type, method_name: str, original: Any, mode: st
552
587
  session = candidate
553
588
  break
554
589
  if session is not None:
555
- if mode == "coordinator":
590
+ if active_mode == "coordinator":
556
591
  assert_model_write_allowed(cls, method_name, session=session)
557
592
  # Defer to the active Session.
558
593
  return await _defer_to_session(
@@ -565,10 +600,10 @@ def _wrap_classmethod(model_cls: type, method_name: str, original: Any, mode: st
565
600
  )
566
601
 
567
602
  # No active Session.
568
- if mode == "coordinator":
603
+ if active_mode == "coordinator":
569
604
  assert_model_write_allowed(cls, method_name)
570
605
 
571
- if mode == "strict":
606
+ if active_mode == "strict":
572
607
  banner = _format_violation_banner(cls.__name__, method_name)
573
608
  vcprint(banner, color="red")
574
609
  logger.error(
@@ -750,15 +785,20 @@ def _format_coordinator_banner(
750
785
  return (
751
786
  "\n"
752
787
  "████████████████████████████████████████████████████████████████████\n"
753
- "██ COORDINATOR-OWNED TABLEDIRECT WRITE FORBIDDEN ██\n"
788
+ "██ COORDINATOR OWNERSHIP BYPASS — WRITE CONTINUED ██\n"
754
789
  "████████████████████████████████████████████████████████████████████\n"
755
790
  f" Model : {model_name}\n"
756
791
  f" Operation : {op_kind}\n"
757
792
  f" Required : Session(write_scope={required_scope!r})\n"
758
793
  f" Actual : Session(write_scope={actual_scope!r})\n"
794
+ " Result : the write was NOT blocked, but bypassed its owner.\n"
759
795
  " Fix : queue this write through the registered Coordinator.\n"
760
- " Exception : allow_direct_managed_write(Model, reason='...')\n"
761
- " is reserved for genuine out-of-request maintenance.\n"
796
+ " Override : allow_direct_coordinator_write(\n"
797
+ " Model, reason='...',\n"
798
+ " acknowledgement=\n"
799
+ f" {COORDINATOR_BYPASS_ACKNOWLEDGEMENT!r},\n"
800
+ " )\n"
801
+ " is reserved for intentional out-of-request writes.\n"
762
802
  "████████████████████████████████████████████████████████████████████\n"
763
803
  )
764
804
 
@@ -233,6 +233,7 @@ class Session:
233
233
  "_opened_at",
234
234
  "_stack_token",
235
235
  "_write_scope",
236
+ "_write_authority",
236
237
  )
237
238
 
238
239
  def __init__(
@@ -243,6 +244,7 @@ class Session:
243
244
  expected_writes: int | None = None,
244
245
  max_age_secs: int | None = None,
245
246
  write_scope: str | None = None,
247
+ _write_authority: object | None = None,
246
248
  ) -> None:
247
249
  self._id = str(uuid.uuid4())
248
250
  self._database = database
@@ -256,6 +258,7 @@ class Session:
256
258
  self._opened_at = datetime.now(UTC)
257
259
  self._stack_token: Any = None
258
260
  self._write_scope = write_scope
261
+ self._write_authority = _write_authority
259
262
 
260
263
  # ---------------------- properties / introspection -------------------
261
264
 
@@ -285,6 +288,9 @@ class Session:
285
288
  """
286
289
  return self._write_scope
287
290
 
291
+ def _has_write_authority(self, authority: object) -> bool:
292
+ return self._write_authority is authority
293
+
288
294
  @property
289
295
  def report(self) -> FlushReport | None:
290
296
  return self._report
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "3.1.10"
3
+ version = "3.1.11"
4
4
  description = "Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -109,7 +109,7 @@ class TestDeclareManagedRegistersStrictTable:
109
109
 
110
110
 
111
111
  class TestCoordinatorOwnedGuard:
112
- def test_plain_session_cannot_defer_to_owned_model(self):
112
+ def test_plain_session_warns_but_still_defers(self, caplog):
113
113
  model = _make_model(
114
114
  "OwnedThing",
115
115
  {"id": UUIDField(primary_key=True), "_table_name": "owned_thing"},
@@ -117,12 +117,12 @@ class TestCoordinatorOwnedGuard:
117
117
  M.declare_managed(model, mode="coordinator", write_scope="request_writer")
118
118
 
119
119
  from matrx_orm import Session
120
- from matrx_orm.session.errors import CoordinatorWriteViolation
121
-
122
- with pytest.raises(CoordinatorWriteViolation):
123
- Session().defer_insert(model, {"id": "abc"})
120
+ session = Session()
121
+ session.defer_insert(model, {"id": "abc"})
122
+ assert session.ops_count == 1
123
+ assert "COORDINATOR OWNERSHIP BYPASS" in caplog.text
124
124
 
125
- def test_matching_session_scope_can_defer(self):
125
+ def test_forged_scope_warns_but_still_defers(self, caplog):
126
126
  model = _make_model(
127
127
  "OwnedThing",
128
128
  {"id": UUIDField(primary_key=True), "_table_name": "owned_thing"},
@@ -134,8 +134,22 @@ class TestCoordinatorOwnedGuard:
134
134
  session = Session(write_scope="request_writer")
135
135
  session.defer_insert(model, {"id": "abc"})
136
136
  assert session.ops_count == 1
137
+ assert "COORDINATOR OWNERSHIP BYPASS" in caplog.text
138
+
139
+ def test_real_coordinator_authority_is_silent(self, caplog):
140
+ model = _make_model(
141
+ "OwnedThing",
142
+ {"id": UUIDField(primary_key=True), "_table_name": "owned_thing"},
143
+ )
144
+ M.declare_managed(model, mode="coordinator")
145
+
146
+ caplog.clear()
147
+ session = M._coordinator_session()
148
+ session.defer_insert(model, {"id": "abc"})
149
+ assert session.ops_count == 1
150
+ assert not [r for r in caplog.records if r.name == "matrx_orm.session.managed"]
137
151
 
138
- def test_reason_bearing_exception_allows_plain_session(self):
152
+ def test_acknowledged_exception_is_silent(self, caplog):
139
153
  model = _make_model(
140
154
  "OwnedThing",
141
155
  {"id": UUIDField(primary_key=True), "_table_name": "owned_thing"},
@@ -144,8 +158,37 @@ class TestCoordinatorOwnedGuard:
144
158
 
145
159
  from matrx_orm import Session
146
160
 
147
- with M.allow_direct_managed_write(model, reason="repair migration 0044"):
161
+ caplog.clear()
162
+ with M.allow_direct_coordinator_write(
163
+ model,
164
+ reason="repair migration 0044",
165
+ acknowledgement=M.COORDINATOR_BYPASS_ACKNOWLEDGEMENT,
166
+ ):
148
167
  Session().defer_insert(model, {"id": "abc"})
168
+ assert not [r for r in caplog.records if r.name == "matrx_orm.session.managed"]
169
+
170
+ def test_override_does_not_authorize_another_model(self, caplog):
171
+ allowed_model = _make_model(
172
+ "AllowedThing",
173
+ {"id": UUIDField(primary_key=True), "_table_name": "allowed_thing"},
174
+ )
175
+ other_model = _make_model(
176
+ "OtherThing",
177
+ {"id": UUIDField(primary_key=True), "_table_name": "other_thing"},
178
+ )
179
+ M.declare_managed(allowed_model, mode="coordinator")
180
+ M.declare_managed(other_model, mode="coordinator")
181
+
182
+ from matrx_orm import Session
183
+
184
+ caplog.clear()
185
+ with M.allow_direct_coordinator_write(
186
+ allowed_model,
187
+ reason="one-model maintenance",
188
+ acknowledgement=M.COORDINATOR_BYPASS_ACKNOWLEDGEMENT,
189
+ ):
190
+ Session().defer_insert(other_model, {"id": "abc"})
191
+ assert "COORDINATOR OWNERSHIP BYPASS" in caplog.text
149
192
 
150
193
  def test_empty_exception_reason_is_rejected(self):
151
194
  model = _make_model(
@@ -153,5 +196,31 @@ class TestCoordinatorOwnedGuard:
153
196
  {"id": UUIDField(primary_key=True), "_table_name": "owned_thing"},
154
197
  )
155
198
  with pytest.raises(ValueError):
156
- with M.allow_direct_managed_write(model, reason=" "):
199
+ with M.allow_direct_coordinator_write(
200
+ model,
201
+ reason=" ",
202
+ acknowledgement=M.COORDINATOR_BYPASS_ACKNOWLEDGEMENT,
203
+ ):
204
+ pass
205
+
206
+ def test_wrong_acknowledgement_is_rejected(self):
207
+ model = _make_model(
208
+ "OwnedThing",
209
+ {"id": UUIDField(primary_key=True), "_table_name": "owned_thing"},
210
+ )
211
+ with pytest.raises(ValueError):
212
+ with M.allow_direct_coordinator_write(
213
+ model,
214
+ reason="repair migration 0044",
215
+ acknowledgement="yes",
216
+ ):
157
217
  pass
218
+
219
+ def test_raw_write_warns_but_does_not_raise(self, caplog):
220
+ model = _make_model(
221
+ "OwnedThing",
222
+ {"id": UUIDField(primary_key=True), "_table_name": "owned_thing"},
223
+ )
224
+ M.declare_managed(model, mode="coordinator")
225
+ M.assert_managed_write_allowed("UPDATE owned_thing SET x=1")
226
+ assert "COORDINATOR OWNERSHIP BYPASS" in caplog.text
File without changes
File without changes
File without changes
File without changes