GeneralManager 0.89.2__tar.gz → 0.90.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 (379) hide show
  1. {generalmanager-0.89.2/src/GeneralManager.egg-info → generalmanager-0.90.0}/PKG-INFO +1 -1
  2. {generalmanager-0.89.2 → generalmanager-0.90.0}/pyproject.toml +1 -1
  3. {generalmanager-0.89.2 → generalmanager-0.90.0/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/GeneralManager.egg-info/SOURCES.txt +2 -0
  5. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql.py +42 -4
  6. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_query_permissions.py +53 -6
  7. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_resolvers.py +16 -1
  8. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/base_interface.py +12 -3
  9. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/mutations.py +242 -14
  10. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +54 -7
  11. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/request/__init__.py +20 -5
  12. generalmanager-0.90.0/src/general_manager/interface/capabilities/request/relation_inputs.py +249 -0
  13. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/manager/general_manager.py +22 -5
  14. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/manager_based_permission.py +142 -18
  15. generalmanager-0.90.0/src/general_manager/permission/permission_data_manager.py +443 -0
  16. generalmanager-0.90.0/src/general_manager/permission/relation_aliases.py +58 -0
  17. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/authorization.py +4 -1
  18. generalmanager-0.89.2/src/general_manager/permission/permission_data_manager.py +0 -132
  19. {generalmanager-0.89.2 → generalmanager-0.90.0}/LICENSE +0 -0
  20. {generalmanager-0.89.2 → generalmanager-0.90.0}/README.md +0 -0
  21. {generalmanager-0.89.2 → generalmanager-0.90.0}/setup.cfg +0 -0
  22. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  23. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/GeneralManager.egg-info/requires.txt +0 -0
  24. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/GeneralManager.egg-info/top_level.txt +0 -0
  25. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/__init__.py +0 -0
  26. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/__init__.py +0 -0
  27. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/api.py +0 -0
  28. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/bucket.py +0 -0
  29. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/cache.py +0 -0
  30. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/dataframes.py +0 -0
  31. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/factory.py +0 -0
  32. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/general_manager.py +0 -0
  33. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/interface.py +0 -0
  34. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/manager.py +0 -0
  35. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/measurement.py +0 -0
  36. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/permission.py +0 -0
  37. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/rule.py +0 -0
  38. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/search.py +0 -0
  39. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/_types/utils.py +0 -0
  40. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/__init__.py +0 -0
  41. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_as_of.py +0 -0
  42. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_errors.py +0 -0
  43. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_filter_contract.py +0 -0
  44. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_groups.py +0 -0
  45. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_identifiers.py +0 -0
  46. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_mutations.py +0 -0
  47. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_ordering.py +0 -0
  48. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_output.py +0 -0
  49. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_prefetch.py +0 -0
  50. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_relations.py +0 -0
  51. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_search.py +0 -0
  52. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  53. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_subscriptions.py +0 -0
  54. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_type.py +0 -0
  55. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_units.py +0 -0
  56. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_value_contract.py +0 -0
  57. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_view.py +0 -0
  58. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_warmup.py +0 -0
  59. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  60. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  61. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/mutation.py +0 -0
  62. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/mutation_controls.py +0 -0
  63. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/notification_batching.py +0 -0
  64. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/property.py +0 -0
  65. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/registry.py +0 -0
  66. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/remote_api.py +0 -0
  67. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/remote_invalidation.py +0 -0
  68. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/api/remote_invalidation_client.py +0 -0
  69. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/apps.py +0 -0
  70. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/as_of.py +0 -0
  71. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bootstrap.py +0 -0
  72. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/__init__.py +0 -0
  73. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/_materialized_bucket.py +0 -0
  74. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/_ordering.py +0 -0
  75. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/base_bucket.py +0 -0
  76. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/calculation_bucket.py +0 -0
  77. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/database_bucket.py +0 -0
  78. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/excel_bucket.py +0 -0
  79. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/group_bucket.py +0 -0
  80. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/indexing.py +0 -0
  81. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/projection.py +0 -0
  82. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/bucket/request_bucket.py +0 -0
  83. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/__init__.py +0 -0
  84. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/_dependency_graph.py +0 -0
  85. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/batch_refresh.py +0 -0
  86. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/cache_decorator.py +0 -0
  87. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/cache_tracker.py +0 -0
  88. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/data_change_context.py +0 -0
  89. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/dependency_cache.py +0 -0
  90. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/dependency_index.py +0 -0
  91. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/dependency_matching.py +0 -0
  92. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/dependency_publish.py +0 -0
  93. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/dependency_shards.py +0 -0
  94. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/model_dependency_collector.py +0 -0
  95. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/run_context.py +0 -0
  96. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/run_context_lru.py +0 -0
  97. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/signals.py +0 -0
  98. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/cache/transaction_barrier.py +0 -0
  99. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/__init__.py +0 -0
  100. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/audit.py +0 -0
  101. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/audit_identity.py +0 -0
  102. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/bootstrap.py +0 -0
  103. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/checks.py +0 -0
  104. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/consumer.py +0 -0
  105. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/context.py +0 -0
  106. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/errors.py +0 -0
  107. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/__init__.py +0 -0
  108. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/__main__.py +0 -0
  109. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/baseline.py +0 -0
  110. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  111. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  112. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  113. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  114. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  115. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  116. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
  117. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/diagnostics.py +0 -0
  118. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/execution.py +0 -0
  119. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/fingerprints.py +0 -0
  120. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/fixtures.py +0 -0
  121. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  122. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  123. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/judges/contract.py +0 -0
  124. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  125. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/judges/result_set.py +0 -0
  126. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  127. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/outcomes.py +0 -0
  128. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/readiness.py +0 -0
  129. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/runner.py +0 -0
  130. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/evals/traces.py +0 -0
  131. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/graphql_contract.py +0 -0
  132. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/grounding.py +0 -0
  133. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/models.py +0 -0
  134. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/mutation_inputs.py +0 -0
  135. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/__init__.py +0 -0
  136. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/action_contract.py +0 -0
  137. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/binding_diagnostics.py +0 -0
  138. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/budget.py +0 -0
  139. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/calculation_scope.py +0 -0
  140. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/calculations.py +0 -0
  141. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/catalog.py +0 -0
  142. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/category_binding.py +0 -0
  143. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/choice_context.py +0 -0
  144. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/clarification.py +0 -0
  145. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/config.py +0 -0
  146. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/contract.py +0 -0
  147. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/conversion.py +0 -0
  148. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/cross_query.py +0 -0
  149. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/deferred_calculations.py +0 -0
  150. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/deferred_schema.py +0 -0
  151. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/events.py +0 -0
  152. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/evidence.py +0 -0
  153. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/evidence_selection.py +0 -0
  154. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/group_actions.py +0 -0
  155. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/models.py +0 -0
  156. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/planner.py +0 -0
  157. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/planner_context.py +0 -0
  158. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/provider_calls.py +0 -0
  159. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/resolver.py +0 -0
  160. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/scheduler.py +0 -0
  161. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/schema_projection.py +0 -0
  162. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/selector_clarification.py +0 -0
  163. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/selector_question.py +0 -0
  164. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/synthesis.py +0 -0
  165. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/planned/validation.py +0 -0
  166. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/providers/__init__.py +0 -0
  167. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/providers/_shared.py +0 -0
  168. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/providers/anthropic.py +0 -0
  169. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/providers/base.py +0 -0
  170. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/providers/google.py +0 -0
  171. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/providers/ollama.py +0 -0
  172. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/providers/openai.py +0 -0
  173. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/rate_limits.py +0 -0
  174. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/routing.py +0 -0
  175. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/schema_index.py +0 -0
  176. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/schema_inspection.py +0 -0
  177. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/settings.py +0 -0
  178. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/signals.py +0 -0
  179. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/system_prompt.py +0 -0
  180. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/tool_metadata.py +0 -0
  181. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/tools.py +0 -0
  182. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/turns.py +0 -0
  183. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/chat/views.py +0 -0
  184. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/conf.py +0 -0
  185. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/dataframes/__init__.py +0 -0
  186. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/dataframes/measurements.py +0 -0
  187. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/factory/__init__.py +0 -0
  188. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/factory/auto_factory.py +0 -0
  189. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/factory/factories.py +0 -0
  190. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/factory/factory_methods.py +0 -0
  191. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/__init__.py +0 -0
  192. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/bundles/__init__.py +0 -0
  193. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/bundles/calculation.py +0 -0
  194. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/bundles/database.py +0 -0
  195. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/bundles/excel.py +0 -0
  196. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  197. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/bundles/request.py +0 -0
  198. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/__init__.py +0 -0
  199. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/base.py +0 -0
  200. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/builtin.py +0 -0
  201. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  202. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  203. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/calculation/input_resolution.py +0 -0
  204. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  205. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/configuration.py +0 -0
  206. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  207. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  208. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
  209. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  210. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  211. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  212. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  213. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/factory.py +0 -0
  214. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  215. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  216. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/bulk.py +0 -0
  217. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/create_many.py +0 -0
  218. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  219. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/history_query.py +0 -0
  220. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  221. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  222. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  223. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm_utils/collection_probes.py +0 -0
  224. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  225. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  226. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
  227. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  228. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  229. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  230. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  231. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  232. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/registry.py +0 -0
  233. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  234. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/excel.py +0 -0
  235. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/excel_store.py +0 -0
  236. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/excel_workbook.py +0 -0
  237. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  238. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  239. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  240. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/__init__.py +0 -0
  241. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/calculation.py +0 -0
  242. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/database.py +0 -0
  243. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/excel.py +0 -0
  244. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  245. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/read_only.py +0 -0
  246. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  247. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/interfaces/request.py +0 -0
  248. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/manifests/__init__.py +0 -0
  249. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  250. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  251. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/manifests/capability_models.py +0 -0
  252. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/orm_interface.py +0 -0
  253. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/requests.py +0 -0
  254. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/unit_contract.py +0 -0
  255. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/utils/__init__.py +0 -0
  256. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  257. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/utils/errors.py +0 -0
  258. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/utils/history.py +0 -0
  259. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/interface/utils/models.py +0 -0
  260. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/logging.py +0 -0
  261. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  262. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  263. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  264. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  265. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/search_index.py +0 -0
  266. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/search_reconcile.py +0 -0
  267. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  268. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/shell.py +0 -0
  269. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/sync_read_only.py +0 -0
  270. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  271. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  272. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/manager/__init__.py +0 -0
  273. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/manager/bulk_create.py +0 -0
  274. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/manager/group_manager.py +0 -0
  275. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/manager/input.py +0 -0
  276. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/manager/meta.py +0 -0
  277. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/measurement/__init__.py +0 -0
  278. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/measurement/measurement.py +0 -0
  279. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/measurement/measurement_field.py +0 -0
  280. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/metrics/__init__.py +0 -0
  281. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/metrics/graphql.py +0 -0
  282. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0001_initial.py +0 -0
  283. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  284. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  285. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  286. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  287. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  288. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  289. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  290. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  291. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  292. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
  293. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
  294. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
  295. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/migrations/__init__.py +0 -0
  296. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/models.py +0 -0
  297. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/__init__.py +0 -0
  298. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/audit.py +0 -0
  299. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/base_permission.py +0 -0
  300. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/graphql_capabilities.py +0 -0
  301. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/mutation_permission.py +0 -0
  302. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/permission_checks.py +0 -0
  303. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/permission/utils.py +0 -0
  304. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/public_api_registry.py +0 -0
  305. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/py.typed +0 -0
  306. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/rule/__init__.py +0 -0
  307. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/rule/handler.py +0 -0
  308. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/rule/rule.py +0 -0
  309. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/__init__.py +0 -0
  310. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/async_tasks.py +0 -0
  311. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/backend.py +0 -0
  312. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/backend_registry.py +0 -0
  313. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/backends/__init__.py +0 -0
  314. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/backends/dev.py +0 -0
  315. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/backends/meilisearch.py +0 -0
  316. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/backends/opensearch.py +0 -0
  317. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/backends/typesense.py +0 -0
  318. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/checks.py +0 -0
  319. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/config.py +0 -0
  320. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/identity.py +0 -0
  321. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/indexer.py +0 -0
  322. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/invalidation.py +0 -0
  323. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/m2m_invalidation.py +0 -0
  324. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/models.py +0 -0
  325. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/projection.py +0 -0
  326. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/reconciliation.py +0 -0
  327. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/registry.py +0 -0
  328. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/tasks.py +0 -0
  329. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/search/utils.py +0 -0
  330. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/seeding/__init__.py +0 -0
  331. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/seeding/manager_landscape.py +0 -0
  332. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/__init__.py +0 -0
  333. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/adapters.py +0 -0
  334. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/checks.py +0 -0
  335. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/config.py +0 -0
  336. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/errors.py +0 -0
  337. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/finalization.py +0 -0
  338. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/graphql.py +0 -0
  339. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/graphql_types.py +0 -0
  340. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/metrics.py +0 -0
  341. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/models.py +0 -0
  342. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/public.py +0 -0
  343. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/s3.py +0 -0
  344. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/services.py +0 -0
  345. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/tokens.py +0 -0
  346. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/types.py +0 -0
  347. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/urls.py +0 -0
  348. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/uploads/views.py +0 -0
  349. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/__init__.py +0 -0
  350. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/_args_to_kwargs.py +0 -0
  351. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/_cache_key_encoder.py +0 -0
  352. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/_make_cache_key.py +0 -0
  353. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/_none_to_zero.py +0 -0
  354. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/executable_contract.py +0 -0
  355. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/filter_parser.py +0 -0
  356. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/format_string.py +0 -0
  357. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/json_encoder.py +0 -0
  358. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/path_mapping.py +0 -0
  359. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/public_api.py +0 -0
  360. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/testing.py +0 -0
  361. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/utils/type_checks.py +0 -0
  362. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/__init__.py +0 -0
  363. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/actions.py +0 -0
  364. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/backend_registry.py +0 -0
  365. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/backends/__init__.py +0 -0
  366. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/backends/celery.py +0 -0
  367. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/backends/local.py +0 -0
  368. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/backends/n8n.py +0 -0
  369. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/config.py +0 -0
  370. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/engine.py +0 -0
  371. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/event_registry.py +0 -0
  372. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/events.py +0 -0
  373. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/models.py +0 -0
  374. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/signal_bridge.py +0 -0
  375. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/tasks.py +0 -0
  376. {generalmanager-0.89.2 → generalmanager-0.90.0}/src/general_manager/workflow/telemetry.py +0 -0
  377. {generalmanager-0.89.2 → generalmanager-0.90.0}/tests/test_settings.py +0 -0
  378. {generalmanager-0.89.2 → generalmanager-0.90.0}/tests/test_urls.py +0 -0
  379. {generalmanager-0.89.2 → generalmanager-0.90.0}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.89.2
3
+ Version: 0.90.0
4
4
  Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "GeneralManager"
7
- version = "0.89.2"
7
+ version = "0.90.0"
8
8
  description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.89.2
3
+ Version: 0.90.0
4
4
  Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License: MIT License
@@ -232,6 +232,7 @@ src/general_manager/interface/capabilities/read_only/_types.py
232
232
  src/general_manager/interface/capabilities/read_only/lifecycle.py
233
233
  src/general_manager/interface/capabilities/read_only/management.py
234
234
  src/general_manager/interface/capabilities/request/__init__.py
235
+ src/general_manager/interface/capabilities/request/relation_inputs.py
235
236
  src/general_manager/interface/infrastructure/__init__.py
236
237
  src/general_manager/interface/infrastructure/startup_hooks.py
237
238
  src/general_manager/interface/infrastructure/system_checks.py
@@ -296,6 +297,7 @@ src/general_manager/permission/manager_based_permission.py
296
297
  src/general_manager/permission/mutation_permission.py
297
298
  src/general_manager/permission/permission_checks.py
298
299
  src/general_manager/permission/permission_data_manager.py
300
+ src/general_manager/permission/relation_aliases.py
299
301
  src/general_manager/permission/utils.py
300
302
  src/general_manager/rule/__init__.py
301
303
  src/general_manager/rule/handler.py
@@ -246,6 +246,23 @@ def _contains_measurement(annotation: object) -> bool:
246
246
  return any(_contains_measurement(argument) for argument in get_args(annotation))
247
247
 
248
248
 
249
+ class InvalidGraphQLMutationDefaultError(TypeError):
250
+ """Raised when the global generated CRUD default is not boolean."""
251
+
252
+ def __init__(self) -> None:
253
+ super().__init__("GRAPHQL_MUTATIONS_ENABLED must be a bool.")
254
+
255
+
256
+ class InvalidGraphQLMutationConfigurationError(TypeError):
257
+ """Raised when a manager's generated CRUD allowlist is invalid."""
258
+
259
+ def __init__(self, manager_name: str) -> None:
260
+ super().__init__(
261
+ f"{manager_name}.__graphql_mutations__ must be a set or frozenset "
262
+ "containing only 'create', 'update', and 'delete'."
263
+ )
264
+
265
+
249
266
  class GraphQLOutputTypeError(ValueError):
250
267
  """Raised when an output declaration cannot be registered safely."""
251
268
 
@@ -724,7 +741,14 @@ class GraphQL:
724
741
  registering anything. Otherwise, it generates create/update/delete
725
742
  mutation classes when the manager's Interface advertises support for the
726
743
  corresponding operation: either by overriding the `InterfaceBase` method
727
- or by listing the operation in `Interface.get_capabilities()`. Each
744
+ or by listing the operation in `Interface.get_capabilities()`. The
745
+ manager's `__graphql_mutations__` set or frozenset must also include that
746
+ operation. When omitted, the global GRAPHQL_MUTATIONS_ENABLED setting
747
+ defaults to True (all three operations); False hides all. Explicit
748
+ inherited allowlists override that default. An empty set
749
+ disables generated CRUD without changing Python writes, permissions,
750
+ queries, or separately registered custom mutations. Invalid allowlists
751
+ raise `TypeError` before mutation registration changes. Each
728
752
  successfully generated mutation is stored on the class-level registry
729
753
  (`_mutations`) under the names `create<ManagerName>`,
730
754
  `update<ManagerName>`, and `delete<ManagerName>`. If a mutation factory
@@ -741,6 +765,20 @@ class GraphQL:
741
765
  if not interface_cls:
742
766
  return None
743
767
 
768
+ supported_mutations = {"create", "update", "delete"}
769
+ global_default = get_setting("GRAPHQL_MUTATIONS_ENABLED", True)
770
+ if not isinstance(global_default, bool):
771
+ raise InvalidGraphQLMutationDefaultError()
772
+ graphql_mutations = getattr(
773
+ generalManagerClass,
774
+ "__graphql_mutations__",
775
+ supported_mutations if global_default else frozenset(),
776
+ )
777
+ if not isinstance(graphql_mutations, (set, frozenset)) or not (
778
+ graphql_mutations <= supported_mutations
779
+ ):
780
+ raise InvalidGraphQLMutationConfigurationError(generalManagerClass.__name__)
781
+
744
782
  default_return_values = {
745
783
  "success": graphene.Boolean(),
746
784
  generalManagerClass.__name__: graphene.Field(
@@ -765,7 +803,7 @@ class GraphQL:
765
803
  method_overridden = base_method.__code__ != method.__code__
766
804
  return method_overridden or op_name in capabilities
767
805
 
768
- if _supports("create", "create"):
806
+ if "create" in graphql_mutations and _supports("create", "create"):
769
807
  create_name = f"create{generalManagerClass.__name__}"
770
808
  create_mutation = cls.generate_create_mutation_class(
771
809
  generalManagerClass, default_return_values
@@ -780,7 +818,7 @@ class GraphQL:
780
818
  },
781
819
  )
782
820
 
783
- if _supports("update", "update"):
821
+ if "update" in graphql_mutations and _supports("update", "update"):
784
822
  update_name = f"update{generalManagerClass.__name__}"
785
823
  update_mutation = cls.generate_update_mutation_class(
786
824
  generalManagerClass, default_return_values
@@ -795,7 +833,7 @@ class GraphQL:
795
833
  },
796
834
  )
797
835
 
798
- if _supports("delete", "delete"):
836
+ if "delete" in graphql_mutations and _supports("delete", "delete"):
799
837
  delete_name = f"delete{generalManagerClass.__name__}"
800
838
  delete_mutation = cls.generate_delete_mutation_class(
801
839
  generalManagerClass, default_return_values
@@ -219,7 +219,7 @@ class _NativeQueryStructure:
219
219
  for name in names:
220
220
  if name not in self.additional:
221
221
  self.additional[name] = additional_local_read_permission(
222
- self.permission, name
222
+ self.permission, name, manager=self.manager
223
223
  )
224
224
  if self.additional[name] is None:
225
225
  return None
@@ -459,7 +459,8 @@ def authorize_query_fields(
459
459
  if getattr_static(permission, "__based_on__", None) is not None:
460
460
  return True
461
461
  return any(
462
- additional_local_read_permission(permission, name) is not False
462
+ additional_local_read_permission(permission, name, manager=type(instance))
463
+ is not False
463
464
  for name in names
464
465
  )
465
466
 
@@ -490,8 +491,37 @@ def authorize_query_fields(
490
491
  aliases, names, native_relations = _operand_field_names(
491
492
  type(instance), field, attributes, native_paths=native_paths
492
493
  )
493
- if budget_additional_permissions_only and needs_additional_budget(
494
- instance, names
494
+ # A standard delegated policy already resolves its concrete target
495
+ # during the normal field check. Inspect that same permission object,
496
+ # not a second relation read or a static declared target type.
497
+ from general_manager.permission.manager_based_permission import (
498
+ _can_prepare_local_read_definitions,
499
+ additional_resolved_read_permission,
500
+ )
501
+ from general_manager.permission.base_permission import BasePermission
502
+
503
+ permission = getattr_static(instance, "Permission", None)
504
+ resolved_budget = (
505
+ budget_additional_permissions_only
506
+ and getattr_static(permission, "__based_on__", None) is not None
507
+ and _can_prepare_local_read_definitions(permission)
508
+ )
509
+ charged = False
510
+
511
+ def charge_resolved(resolved: BasePermission, name: str) -> None:
512
+ """Charge this operand once when its resolved policy adds or may add restrictions."""
513
+ nonlocal charged
514
+ if (
515
+ not charged
516
+ and additional_resolved_read_permission(resolved, name) is not False
517
+ ):
518
+ budget.charge()
519
+ charged = True
520
+
521
+ if (
522
+ budget_additional_permissions_only
523
+ and not resolved_budget
524
+ and needs_additional_budget(instance, names)
495
525
  ):
496
526
  budget.charge()
497
527
  known_fields = set(attributes) | set(instance.identification)
@@ -500,8 +530,25 @@ def authorize_query_fields(
500
530
  known_fields.update(instance.Interface.input_fields)
501
531
  if not names.intersection(known_fields):
502
532
  raise QueryFieldPermissionError(field)
503
- if any(not check_read_permission(instance, info, name) for name in names):
504
- raise QueryFieldPermissionError(field)
533
+ for name in names:
534
+ if resolved_budget:
535
+
536
+ def before_check(
537
+ resolved: BasePermission, field_name: str = name
538
+ ) -> None:
539
+ """Account for the exact resolved permission before its normal field check."""
540
+ charge_resolved(resolved, field_name)
541
+
542
+ allowed = check_read_permission(
543
+ instance,
544
+ info,
545
+ name,
546
+ before_check=before_check,
547
+ )
548
+ else:
549
+ allowed = check_read_permission(instance, info, name)
550
+ if not allowed:
551
+ raise QueryFieldPermissionError(field)
505
552
  for relation in sorted(native_relations):
506
553
  # An ORM attname is a scalar spelling of a related field. Give it
507
554
  # the same target row/leaf gates as an explicit relation path.
@@ -1140,6 +1140,8 @@ def check_read_permission_for_user(
1140
1140
  instance: GeneralManager,
1141
1141
  user: object,
1142
1142
  field_name: str,
1143
+ *,
1144
+ before_check: Callable[[BasePermission], None] | None = None,
1143
1145
  ) -> bool:
1144
1146
  """
1145
1147
  Return ``True`` if *user* may read *field_name* on *instance*.
@@ -1147,10 +1149,15 @@ def check_read_permission_for_user(
1147
1149
  When the manager defines a Permission class, this calls
1148
1150
  ``Permission(instance, user).check_permission("read", field_name)``.
1149
1151
  Managers without a Permission class default to allowing the field read.
1152
+ The internal ``before_check`` hook may account for the resolved policy,
1153
+ without constructing it twice or replacing its authorization decision.
1150
1154
  """
1151
1155
  PermissionClass: type[BasePermission] | None = getattr(instance, "Permission", None)
1152
1156
  if PermissionClass:
1153
- return PermissionClass(instance, user).check_permission("read", field_name)
1157
+ permission = PermissionClass(instance, user)
1158
+ if before_check is not None:
1159
+ before_check(permission)
1160
+ return permission.check_permission("read", field_name)
1154
1161
  return True
1155
1162
 
1156
1163
 
@@ -1158,6 +1165,8 @@ def check_read_permission(
1158
1165
  instance: GeneralManager,
1159
1166
  info: GraphQLResolveInfo,
1160
1167
  field_name: str,
1168
+ *,
1169
+ before_check: Callable[[BasePermission], None] | None = None,
1161
1170
  ) -> bool:
1162
1171
  """
1163
1172
  Return ``True`` if the request user may read *field_name* on *instance*.
@@ -1165,7 +1174,13 @@ def check_read_permission(
1165
1174
  When the manager defines a Permission class, this calls
1166
1175
  ``Permission(instance, user).check_permission("read", field_name)``.
1167
1176
  Managers without a Permission class default to allowing the field read.
1177
+ The internal ``before_check`` hook may account for the resolved policy,
1178
+ without constructing it twice or replacing its authorization decision.
1168
1179
  """
1180
+ if before_check is not None:
1181
+ return check_read_permission_for_user(
1182
+ instance, info.context.user, field_name, before_check=before_check
1183
+ )
1169
1184
  return check_read_permission_for_user(instance, info.context.user, field_name)
1170
1185
 
1171
1186
 
@@ -1183,7 +1183,6 @@ class InterfaceBase(ABC):
1183
1183
  The capability-level create result mapping.
1184
1184
  """
1185
1185
  reject_historical_mutation()
1186
- observer = cls.get_capability_handler("observability")
1187
1186
 
1188
1187
  def _invoke() -> dict[str, object]:
1189
1188
  """
@@ -1201,12 +1200,22 @@ class InterfaceBase(ABC):
1201
1200
  return create_handler(cls, *args, **kwargs)
1202
1201
  raise NotImplementedError(f"{cls.__name__} does not support create.")
1203
1202
 
1203
+ return cls._observe_create(args, kwargs, _invoke)
1204
+
1205
+ @classmethod
1206
+ def _observe_create(
1207
+ cls,
1208
+ args: tuple[object, ...],
1209
+ kwargs: dict[str, object],
1210
+ invoke: Callable[[], dict[str, object]],
1211
+ ) -> dict[str, object]:
1212
+ """Share the public create observation envelope with ORM manager writes."""
1204
1213
  return cls._execute_with_observability(
1205
1214
  target=cls,
1206
1215
  operation="create",
1207
1216
  payload={"args": args, "kwargs": kwargs},
1208
- func=_invoke,
1209
- observer=observer,
1217
+ func=invoke,
1218
+ observer=cls.get_capability_handler("observability"),
1210
1219
  )
1211
1220
 
1212
1221
  @classmethod
@@ -5,11 +5,14 @@ from __future__ import annotations
5
5
  from collections.abc import Iterator
6
6
  from contextlib import AbstractContextManager, contextmanager
7
7
  from contextvars import ContextVar
8
- from typing import TYPE_CHECKING, Any, ClassVar, cast
8
+ from copy import copy, deepcopy
9
+ from dataclasses import dataclass, field
10
+ from typing import TYPE_CHECKING, Any, ClassVar, Protocol, cast
9
11
 
10
12
  from django.contrib.auth import get_user_model
11
13
  from django.db import DEFAULT_DB_ALIAS, models, router, transaction
12
14
  from django.db.models import NOT_PROVIDED
15
+ from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor
13
16
 
14
17
  from general_manager.cache.data_change_context import (
15
18
  mark_data_change_unchanged,
@@ -53,7 +56,9 @@ from .support import (
53
56
  )
54
57
 
55
58
  if TYPE_CHECKING: # pragma: no cover
59
+ from django.db.models.fields.reverse_related import ForeignObjectRel
56
60
  from general_manager.interface.orm_interface import OrmInterfaceBase
61
+ from general_manager.manager.general_manager import GeneralManager
57
62
 
58
63
  type OrmInterfaceClass = type["OrmInterfaceBase[models.Model]"]
59
64
  type OrmInterfaceInstance = "OrmInterfaceBase[models.Model]"
@@ -61,6 +66,110 @@ type MutationPayload = dict[str, object]
61
66
  type ManyToManyPayload = dict[str, list[object]]
62
67
  type MutationResult = dict[str, object]
63
68
 
69
+
70
+ class _CreatePermissionTargetChangedError(PermissionError):
71
+ """The prepared create no longer targets the database or key authorized."""
72
+
73
+ def __init__(self) -> None:
74
+ super().__init__("The authorized ORM create relation target changed.")
75
+
76
+
77
+ class _UnboundRoutedCreatePermissionError(PermissionError):
78
+ """A custom writer cannot bind its dynamic route to the permission check."""
79
+
80
+ def __init__(self) -> None:
81
+ super().__init__(
82
+ "Resolving a related object during a custom ORM create "
83
+ "requires a fixed database alias."
84
+ )
85
+
86
+
87
+ @dataclass(slots=True)
88
+ class _RoutedCreatePermission:
89
+ """Share one prepared model between its permission check and write."""
90
+
91
+ manager: type[GeneralManager]
92
+ payload: MutationPayload
93
+ interface: OrmInterfaceClass
94
+ shares_source: bool
95
+ source: models.Model | None = None
96
+ routing_hint: models.Model | None = None
97
+ checked_relations: dict[str, tuple[models.ForeignKey[models.Model], object]] = (
98
+ field(default_factory=dict)
99
+ )
100
+
101
+ def get_source(self) -> models.Model:
102
+ """Initialize Django defaults only when a permission needs the source."""
103
+ if not self.shares_source:
104
+ raise _UnboundRoutedCreatePermissionError
105
+ if self.source is None:
106
+ self.source = self.interface._model()
107
+ return self.source
108
+
109
+ @property
110
+ def database_alias(self) -> str | None:
111
+ """Return the chosen database once the check resolves a related row."""
112
+ return self.routing_hint._state.db if self.routing_hint is not None else None
113
+
114
+ def verify_target(
115
+ self, instance: models.Model, configured_database: str | None
116
+ ) -> None:
117
+ """Reject routing or relation-key changes introduced by model validation."""
118
+ if self.database_alias is not None and self.database_alias != (
119
+ configured_database
120
+ or router.db_for_write(type(instance), instance=instance)
121
+ ):
122
+ raise _CreatePermissionTargetChangedError
123
+ if any(
124
+ relation.target_field.to_python(getattr(instance, attname)) != value
125
+ for attname, (relation, value) in self.checked_relations.items()
126
+ ):
127
+ raise _CreatePermissionTargetChangedError
128
+
129
+
130
+ _routed_create_check = ContextVar[_RoutedCreatePermission | None](
131
+ "routed_create_check", default=None
132
+ )
133
+ _routed_create_write = ContextVar[tuple[models.Model, _RoutedCreatePermission] | None](
134
+ "routed_create_write", default=None
135
+ )
136
+
137
+
138
+ def _copy_create_source(
139
+ source: models.Model, *, isolate_defaults: bool = False
140
+ ) -> models.Model:
141
+ """Copy ORM state, with isolated field defaults for retryable writes."""
142
+ instance = object.__new__(type(source))
143
+ instance.__dict__.update(source.__dict__)
144
+ if isolate_defaults:
145
+ for concrete in source._meta.concrete_fields:
146
+ if concrete.attname in source.__dict__:
147
+ instance.__dict__[concrete.attname] = deepcopy(
148
+ source.__dict__[concrete.attname]
149
+ )
150
+ instance._state = copy(source._state)
151
+ vars(instance._state)["fields_cache"] = dict(
152
+ cast(dict[str, object], source._state.fields_cache)
153
+ )
154
+ return instance
155
+
156
+
157
+ @contextmanager
158
+ def _bind_routed_create_write(
159
+ instance: models.Model,
160
+ permission: _RoutedCreatePermission | None,
161
+ ) -> Iterator[None]:
162
+ """Give the existing save hook the authorization for this exact model."""
163
+ if permission is None:
164
+ yield
165
+ return
166
+ token = _routed_create_write.set((instance, permission))
167
+ try:
168
+ yield
169
+ finally:
170
+ _routed_create_write.reset(token)
171
+
172
+
64
173
  _save_with_history_savepoint = ContextVar(
65
174
  "save_with_history_savepoint",
66
175
  default=True,
@@ -94,6 +203,37 @@ def _mutation_atomic(
94
203
  return transaction.atomic(savepoint=False)
95
204
 
96
205
 
206
+ class _ModelPkState(Protocol):
207
+ """Django's PK completeness check, absent from older stubs."""
208
+
209
+ def _is_pk_set(self) -> bool: ...
210
+
211
+
212
+ def _discard_alternate_key_cache(
213
+ instance: models.Model, name: str, related: models.Model
214
+ ) -> None:
215
+ """Keep Django assignment checks and reload the current alternate-key owner."""
216
+ descriptor = getattr(type(instance), name, None)
217
+ if not isinstance(descriptor, ForwardManyToOneDescriptor):
218
+ return
219
+ relation = descriptor.field
220
+ if (
221
+ not isinstance(relation, models.ForeignKey)
222
+ or relation.target_field.primary_key
223
+ or not cast(_ModelPkState, related)._is_pk_set()
224
+ or not relation.is_cached(instance)
225
+ ):
226
+ # Leave unsaved objects cached so Django still rejects them at save.
227
+ return
228
+ relation.delete_cached_value(instance)
229
+ reverse = cast("ForeignObjectRel", relation.remote_field)
230
+ if (
231
+ not reverse.multiple
232
+ and reverse.get_cached_value(related, default=None) is instance
233
+ ):
234
+ reverse.delete_cached_value(related)
235
+
236
+
97
237
  class OrmMutationCapability(BaseCapability):
98
238
  """Common utilities to modify ORM instances."""
99
239
 
@@ -144,6 +284,8 @@ class OrmMutationCapability(BaseCapability):
144
284
  raise InvalidFieldValueError(key, value) from error
145
285
  except TypeError as error:
146
286
  raise InvalidFieldTypeError(key, error) from error
287
+ if isinstance(value, models.Model):
288
+ _discard_alternate_key_cache(instance, key, value)
147
289
  return instance
148
290
 
149
291
  return call_with_observability(
@@ -202,6 +344,15 @@ class OrmMutationCapability(BaseCapability):
202
344
  """
203
345
  support = get_support_capability(interface_cls)
204
346
  database_alias = support.get_database_alias(interface_cls)
347
+ create_write = _routed_create_write.get()
348
+ create_permission = (
349
+ create_write[1]
350
+ if create_write is not None and create_write[0] is instance
351
+ else None
352
+ )
353
+ write_database = (
354
+ create_permission.database_alias if create_permission else None
355
+ ) or database_alias
205
356
  from general_manager.manager.bulk_create import (
206
357
  CreateManyUnsupportedError,
207
358
  enclosing_create_many_batch,
@@ -216,7 +367,7 @@ class OrmMutationCapability(BaseCapability):
216
367
  if database_alias:
217
368
  instance._state.db = database_alias
218
369
  atomic_context = _mutation_atomic(
219
- database_alias,
370
+ write_database,
220
371
  savepoint=_save_with_history_savepoint.get(),
221
372
  )
222
373
  with atomic_context:
@@ -237,8 +388,10 @@ class OrmMutationCapability(BaseCapability):
237
388
  != batch.database_alias
238
389
  ):
239
390
  raise CreateManyUnsupportedError.routing()
240
- if database_alias:
241
- instance.save(using=database_alias)
391
+ if create_permission is not None:
392
+ create_permission.verify_target(instance, database_alias)
393
+ if write_database:
394
+ instance.save(using=write_database)
242
395
  else:
243
396
  instance.save()
244
397
  return instance.pk
@@ -371,6 +524,16 @@ class OrmCreateCapability(BaseCapability):
371
524
  wrapped.
372
525
  """
373
526
  _ = args
527
+ return self._create(interface_cls, kwargs)
528
+
529
+ def _create(
530
+ self,
531
+ interface_cls: OrmInterfaceClass,
532
+ kwargs: MutationPayload,
533
+ *,
534
+ permission: _RoutedCreatePermission | None = None,
535
+ ) -> MutationResult:
536
+ """Persist a create using the initialized source shared with its check."""
374
537
  payload_snapshot = {"kwargs": dict(kwargs)}
375
538
 
376
539
  def _perform() -> MutationResult:
@@ -399,6 +562,10 @@ class OrmCreateCapability(BaseCapability):
399
562
  if enclosing_create_many_batch() is not None:
400
563
  validate_create_many_record(normalized_simple)
401
564
  mutation = _mutation_capability_for(interface_cls)
565
+ source = permission.source if permission is not None else None
566
+ authorized_database = (
567
+ permission.database_alias if permission is not None else None
568
+ )
402
569
  if has_upload_candidates(normalized_simple):
403
570
  prepared = prepare_upload_claims(
404
571
  interface_cls,
@@ -407,10 +574,18 @@ class OrmCreateCapability(BaseCapability):
407
574
  actor_id=creator_id,
408
575
  target_pk=None,
409
576
  )
577
+ if authorized_database not in (None, prepared.database_alias):
578
+ raise _CreatePermissionTargetChangedError
410
579
 
411
580
  def _create_claimed() -> MutationResult:
412
581
  locked = lock_upload_claims(prepared)
413
- instance = interface_cls._model()
582
+ # An upload may retry the transaction. Each attempt starts
583
+ # with the same authorized defaults and a fresh model state.
584
+ instance = (
585
+ _copy_create_source(source, isolate_defaults=True)
586
+ if source is not None
587
+ else interface_cls._model()
588
+ )
414
589
  ordinary_values = {
415
590
  key: value
416
591
  for key, value in normalized_simple.items()
@@ -431,12 +606,13 @@ class OrmCreateCapability(BaseCapability):
431
606
  instance,
432
607
  reserved_values,
433
608
  )
434
- claimed_pk = mutation.save_with_history(
435
- interface_cls,
436
- claimed_instance,
437
- creator_id=creator_id,
438
- history_comment=history_comment,
439
- )
609
+ with _bind_routed_create_write(claimed_instance, permission):
610
+ claimed_pk = mutation.save_with_history(
611
+ interface_cls,
612
+ claimed_instance,
613
+ creator_id=creator_id,
614
+ history_comment=history_comment,
615
+ )
440
616
  mutation.apply_many_to_many(
441
617
  interface_cls,
442
618
  claimed_instance,
@@ -448,12 +624,16 @@ class OrmCreateCapability(BaseCapability):
448
624
 
449
625
  return run_upload_transaction(prepared, _create_claimed)
450
626
  instance = mutation.assign_simple_attributes(
451
- interface_cls, interface_cls._model(), normalized_simple
627
+ interface_cls,
628
+ source if source is not None else interface_cls._model(),
629
+ normalized_simple,
452
630
  )
453
631
  support = get_support_capability(interface_cls)
454
632
  database_alias = support.get_database_alias(interface_cls)
455
- atomic_context = _mutation_atomic(database_alias)
456
- with atomic_context:
633
+ with (
634
+ _mutation_atomic(authorized_database or database_alias),
635
+ _bind_routed_create_write(instance, permission),
636
+ ):
457
637
  with _without_save_with_history_savepoint():
458
638
  pk = mutation.save_with_history(
459
639
  interface_cls,
@@ -477,6 +657,54 @@ class OrmCreateCapability(BaseCapability):
477
657
  )
478
658
 
479
659
 
660
+ def _create_for_manager(
661
+ interface: OrmInterfaceClass,
662
+ manager: type[GeneralManager],
663
+ payload: MutationPayload,
664
+ creator_id: int | None,
665
+ history_comment: str | None,
666
+ ) -> MutationResult:
667
+ """Use the prepared model for permission checks in canonical routed creates."""
668
+ from general_manager.interface.base_interface import InterfaceBase
669
+
670
+ create = interface.create
671
+ if not router.routers:
672
+ manager.Permission.check_create_permission(payload, manager, creator_id)
673
+ return create(creator_id=creator_id, history_comment=history_comment, **payload)
674
+
675
+ handler = interface.get_capability_handler("create")
676
+ builtin_create = (
677
+ isinstance(handler, OrmCreateCapability)
678
+ and getattr(handler.create, "__func__", None) is OrmCreateCapability.create
679
+ and getattr(create, "__func__", None)
680
+ is getattr(InterfaceBase.create, "__func__", None)
681
+ )
682
+ mutation = interface.get_capability_handler("orm_mutation")
683
+ builtin_save = (
684
+ isinstance(mutation, OrmMutationCapability)
685
+ and getattr(mutation.save_with_history, "__func__", None)
686
+ is OrmMutationCapability.save_with_history
687
+ )
688
+ permission = _RoutedCreatePermission(
689
+ manager, payload, interface, shares_source=builtin_create and builtin_save
690
+ )
691
+ token = _routed_create_check.set(permission)
692
+ try:
693
+ manager.Permission.check_create_permission(payload, manager, creator_id)
694
+ finally:
695
+ _routed_create_check.reset(token)
696
+
697
+ if not builtin_create:
698
+ return create(creator_id=creator_id, history_comment=history_comment, **payload)
699
+ assert isinstance(handler, OrmCreateCapability)
700
+ kwargs = {"creator_id": creator_id, "history_comment": history_comment, **payload}
701
+ return interface._observe_create(
702
+ (),
703
+ kwargs,
704
+ lambda: handler._create(interface, kwargs, permission=permission),
705
+ )
706
+
707
+
480
708
  class OrmUpdateCapability(BaseCapability):
481
709
  """Update existing ORM instances."""
482
710