GeneralManager 0.87.0__tar.gz → 0.87.1__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 (372) hide show
  1. {generalmanager-0.87.0/src/GeneralManager.egg-info → generalmanager-0.87.1}/PKG-INFO +1 -1
  2. {generalmanager-0.87.0 → generalmanager-0.87.1}/pyproject.toml +1 -1
  3. {generalmanager-0.87.0 → generalmanager-0.87.1/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/GeneralManager.egg-info/SOURCES.txt +1 -0
  5. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql.py +29 -4
  6. generalmanager-0.87.1/src/general_manager/api/graphql_query_permissions.py +168 -0
  7. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_resolvers.py +180 -45
  8. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_search.py +134 -24
  9. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_subscription_consumer.py +63 -3
  10. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/tools.py +10 -11
  11. {generalmanager-0.87.0 → generalmanager-0.87.1}/LICENSE +0 -0
  12. {generalmanager-0.87.0 → generalmanager-0.87.1}/README.md +0 -0
  13. {generalmanager-0.87.0 → generalmanager-0.87.1}/setup.cfg +0 -0
  14. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  15. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/GeneralManager.egg-info/requires.txt +0 -0
  16. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/GeneralManager.egg-info/top_level.txt +0 -0
  17. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/__init__.py +0 -0
  18. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/__init__.py +0 -0
  19. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/api.py +0 -0
  20. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/bucket.py +0 -0
  21. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/cache.py +0 -0
  22. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/dataframes.py +0 -0
  23. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/factory.py +0 -0
  24. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/general_manager.py +0 -0
  25. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/interface.py +0 -0
  26. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/manager.py +0 -0
  27. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/measurement.py +0 -0
  28. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/permission.py +0 -0
  29. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/rule.py +0 -0
  30. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/search.py +0 -0
  31. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/_types/utils.py +0 -0
  32. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/__init__.py +0 -0
  33. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_as_of.py +0 -0
  34. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_errors.py +0 -0
  35. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_filter_contract.py +0 -0
  36. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_groups.py +0 -0
  37. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_identifiers.py +0 -0
  38. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_mutations.py +0 -0
  39. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_ordering.py +0 -0
  40. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_output.py +0 -0
  41. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_prefetch.py +0 -0
  42. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_relations.py +0 -0
  43. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_subscriptions.py +0 -0
  44. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_type.py +0 -0
  45. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_units.py +0 -0
  46. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_value_contract.py +0 -0
  47. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_view.py +0 -0
  48. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_warmup.py +0 -0
  49. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  50. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  51. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/mutation.py +0 -0
  52. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/mutation_controls.py +0 -0
  53. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/notification_batching.py +0 -0
  54. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/property.py +0 -0
  55. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/registry.py +0 -0
  56. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/remote_api.py +0 -0
  57. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/remote_invalidation.py +0 -0
  58. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/api/remote_invalidation_client.py +0 -0
  59. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/apps.py +0 -0
  60. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/as_of.py +0 -0
  61. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bootstrap.py +0 -0
  62. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/__init__.py +0 -0
  63. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/_materialized_bucket.py +0 -0
  64. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/_ordering.py +0 -0
  65. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/base_bucket.py +0 -0
  66. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/calculation_bucket.py +0 -0
  67. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/database_bucket.py +0 -0
  68. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/excel_bucket.py +0 -0
  69. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/group_bucket.py +0 -0
  70. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/indexing.py +0 -0
  71. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/projection.py +0 -0
  72. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/bucket/request_bucket.py +0 -0
  73. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/__init__.py +0 -0
  74. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/_dependency_graph.py +0 -0
  75. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/batch_refresh.py +0 -0
  76. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/cache_decorator.py +0 -0
  77. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/cache_tracker.py +0 -0
  78. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/data_change_context.py +0 -0
  79. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/dependency_cache.py +0 -0
  80. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/dependency_index.py +0 -0
  81. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/dependency_matching.py +0 -0
  82. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/dependency_publish.py +0 -0
  83. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/dependency_shards.py +0 -0
  84. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/model_dependency_collector.py +0 -0
  85. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/run_context.py +0 -0
  86. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/run_context_lru.py +0 -0
  87. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/signals.py +0 -0
  88. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/cache/transaction_barrier.py +0 -0
  89. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/__init__.py +0 -0
  90. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/audit.py +0 -0
  91. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/audit_identity.py +0 -0
  92. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/bootstrap.py +0 -0
  93. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/checks.py +0 -0
  94. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/consumer.py +0 -0
  95. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/context.py +0 -0
  96. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/errors.py +0 -0
  97. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/__init__.py +0 -0
  98. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/__main__.py +0 -0
  99. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/baseline.py +0 -0
  100. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  101. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  102. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  103. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  104. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  105. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  106. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
  107. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/diagnostics.py +0 -0
  108. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/execution.py +0 -0
  109. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/fingerprints.py +0 -0
  110. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/fixtures.py +0 -0
  111. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  112. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  113. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/judges/contract.py +0 -0
  114. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  115. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/judges/result_set.py +0 -0
  116. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  117. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/outcomes.py +0 -0
  118. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/readiness.py +0 -0
  119. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/runner.py +0 -0
  120. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/evals/traces.py +0 -0
  121. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/graphql_contract.py +0 -0
  122. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/grounding.py +0 -0
  123. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/models.py +0 -0
  124. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/mutation_inputs.py +0 -0
  125. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/__init__.py +0 -0
  126. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/action_contract.py +0 -0
  127. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/binding_diagnostics.py +0 -0
  128. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/budget.py +0 -0
  129. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/calculation_scope.py +0 -0
  130. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/calculations.py +0 -0
  131. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/catalog.py +0 -0
  132. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/category_binding.py +0 -0
  133. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/choice_context.py +0 -0
  134. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/clarification.py +0 -0
  135. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/config.py +0 -0
  136. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/contract.py +0 -0
  137. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/conversion.py +0 -0
  138. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/cross_query.py +0 -0
  139. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/deferred_calculations.py +0 -0
  140. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/deferred_schema.py +0 -0
  141. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/events.py +0 -0
  142. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/evidence.py +0 -0
  143. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/evidence_selection.py +0 -0
  144. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/group_actions.py +0 -0
  145. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/models.py +0 -0
  146. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/planner.py +0 -0
  147. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/planner_context.py +0 -0
  148. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/provider_calls.py +0 -0
  149. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/resolver.py +0 -0
  150. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/scheduler.py +0 -0
  151. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/schema_projection.py +0 -0
  152. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/selector_clarification.py +0 -0
  153. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/selector_question.py +0 -0
  154. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/synthesis.py +0 -0
  155. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/planned/validation.py +0 -0
  156. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/providers/__init__.py +0 -0
  157. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/providers/_shared.py +0 -0
  158. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/providers/anthropic.py +0 -0
  159. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/providers/base.py +0 -0
  160. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/providers/google.py +0 -0
  161. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/providers/ollama.py +0 -0
  162. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/providers/openai.py +0 -0
  163. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/rate_limits.py +0 -0
  164. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/routing.py +0 -0
  165. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/schema_index.py +0 -0
  166. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/schema_inspection.py +0 -0
  167. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/settings.py +0 -0
  168. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/signals.py +0 -0
  169. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/system_prompt.py +0 -0
  170. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/tool_metadata.py +0 -0
  171. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/turns.py +0 -0
  172. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/chat/views.py +0 -0
  173. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/conf.py +0 -0
  174. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/dataframes/__init__.py +0 -0
  175. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/dataframes/measurements.py +0 -0
  176. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/factory/__init__.py +0 -0
  177. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/factory/auto_factory.py +0 -0
  178. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/factory/factories.py +0 -0
  179. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/factory/factory_methods.py +0 -0
  180. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/__init__.py +0 -0
  181. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/base_interface.py +0 -0
  182. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/bundles/__init__.py +0 -0
  183. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/bundles/calculation.py +0 -0
  184. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/bundles/database.py +0 -0
  185. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/bundles/excel.py +0 -0
  186. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  187. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/bundles/request.py +0 -0
  188. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/__init__.py +0 -0
  189. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/base.py +0 -0
  190. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/builtin.py +0 -0
  191. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  192. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  193. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/calculation/input_resolution.py +0 -0
  194. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  195. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/configuration.py +0 -0
  196. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  197. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  198. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
  199. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  200. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  201. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  202. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  203. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/factory.py +0 -0
  204. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  205. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  206. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/bulk.py +0 -0
  207. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/create_many.py +0 -0
  208. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  209. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  210. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  211. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  212. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  213. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  214. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  215. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  216. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
  217. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  218. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  219. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  220. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  221. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  222. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/registry.py +0 -0
  223. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  224. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  225. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/excel.py +0 -0
  226. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/excel_store.py +0 -0
  227. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/excel_workbook.py +0 -0
  228. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  229. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  230. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  231. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/__init__.py +0 -0
  232. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/calculation.py +0 -0
  233. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/database.py +0 -0
  234. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/excel.py +0 -0
  235. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  236. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/read_only.py +0 -0
  237. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  238. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/interfaces/request.py +0 -0
  239. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/manifests/__init__.py +0 -0
  240. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  241. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  242. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/manifests/capability_models.py +0 -0
  243. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/orm_interface.py +0 -0
  244. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/requests.py +0 -0
  245. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/unit_contract.py +0 -0
  246. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/utils/__init__.py +0 -0
  247. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  248. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/utils/errors.py +0 -0
  249. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/utils/history.py +0 -0
  250. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/interface/utils/models.py +0 -0
  251. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/logging.py +0 -0
  252. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  253. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  254. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  255. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  256. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/search_index.py +0 -0
  257. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/search_reconcile.py +0 -0
  258. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  259. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/shell.py +0 -0
  260. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/sync_read_only.py +0 -0
  261. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  262. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  263. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/manager/__init__.py +0 -0
  264. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/manager/bulk_create.py +0 -0
  265. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/manager/general_manager.py +0 -0
  266. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/manager/group_manager.py +0 -0
  267. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/manager/input.py +0 -0
  268. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/manager/meta.py +0 -0
  269. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/measurement/__init__.py +0 -0
  270. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/measurement/measurement.py +0 -0
  271. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/measurement/measurement_field.py +0 -0
  272. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/metrics/__init__.py +0 -0
  273. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/metrics/graphql.py +0 -0
  274. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0001_initial.py +0 -0
  275. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  276. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  277. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  278. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  279. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  280. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  281. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  282. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  283. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  284. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
  285. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
  286. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
  287. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/migrations/__init__.py +0 -0
  288. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/models.py +0 -0
  289. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/__init__.py +0 -0
  290. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/audit.py +0 -0
  291. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/base_permission.py +0 -0
  292. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/graphql_capabilities.py +0 -0
  293. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/manager_based_permission.py +0 -0
  294. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/mutation_permission.py +0 -0
  295. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/permission_checks.py +0 -0
  296. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/permission_data_manager.py +0 -0
  297. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/permission/utils.py +0 -0
  298. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/public_api_registry.py +0 -0
  299. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/py.typed +0 -0
  300. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/rule/__init__.py +0 -0
  301. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/rule/handler.py +0 -0
  302. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/rule/rule.py +0 -0
  303. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/__init__.py +0 -0
  304. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/async_tasks.py +0 -0
  305. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/backend.py +0 -0
  306. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/backend_registry.py +0 -0
  307. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/backends/__init__.py +0 -0
  308. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/backends/dev.py +0 -0
  309. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/backends/meilisearch.py +0 -0
  310. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/backends/opensearch.py +0 -0
  311. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/backends/typesense.py +0 -0
  312. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/checks.py +0 -0
  313. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/config.py +0 -0
  314. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/identity.py +0 -0
  315. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/indexer.py +0 -0
  316. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/invalidation.py +0 -0
  317. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/m2m_invalidation.py +0 -0
  318. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/models.py +0 -0
  319. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/reconciliation.py +0 -0
  320. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/registry.py +0 -0
  321. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/tasks.py +0 -0
  322. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/search/utils.py +0 -0
  323. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/seeding/__init__.py +0 -0
  324. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/seeding/manager_landscape.py +0 -0
  325. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/__init__.py +0 -0
  326. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/adapters.py +0 -0
  327. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/checks.py +0 -0
  328. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/config.py +0 -0
  329. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/errors.py +0 -0
  330. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/finalization.py +0 -0
  331. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/graphql.py +0 -0
  332. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/graphql_types.py +0 -0
  333. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/metrics.py +0 -0
  334. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/models.py +0 -0
  335. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/public.py +0 -0
  336. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/s3.py +0 -0
  337. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/services.py +0 -0
  338. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/tokens.py +0 -0
  339. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/types.py +0 -0
  340. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/urls.py +0 -0
  341. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/uploads/views.py +0 -0
  342. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/__init__.py +0 -0
  343. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/_args_to_kwargs.py +0 -0
  344. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/_cache_key_encoder.py +0 -0
  345. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/_make_cache_key.py +0 -0
  346. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/_none_to_zero.py +0 -0
  347. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/executable_contract.py +0 -0
  348. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/filter_parser.py +0 -0
  349. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/format_string.py +0 -0
  350. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/json_encoder.py +0 -0
  351. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/path_mapping.py +0 -0
  352. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/public_api.py +0 -0
  353. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/testing.py +0 -0
  354. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/utils/type_checks.py +0 -0
  355. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/__init__.py +0 -0
  356. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/actions.py +0 -0
  357. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/backend_registry.py +0 -0
  358. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/backends/__init__.py +0 -0
  359. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/backends/celery.py +0 -0
  360. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/backends/local.py +0 -0
  361. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/backends/n8n.py +0 -0
  362. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/config.py +0 -0
  363. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/engine.py +0 -0
  364. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/event_registry.py +0 -0
  365. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/events.py +0 -0
  366. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/models.py +0 -0
  367. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/signal_bridge.py +0 -0
  368. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/tasks.py +0 -0
  369. {generalmanager-0.87.0 → generalmanager-0.87.1}/src/general_manager/workflow/telemetry.py +0 -0
  370. {generalmanager-0.87.0 → generalmanager-0.87.1}/tests/test_settings.py +0 -0
  371. {generalmanager-0.87.0 → generalmanager-0.87.1}/tests/test_urls.py +0 -0
  372. {generalmanager-0.87.0 → generalmanager-0.87.1}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.87.0
3
+ Version: 0.87.1
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.87.0"
7
+ version = "0.87.1"
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.87.0
3
+ Version: 0.87.1
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
@@ -40,6 +40,7 @@ src/general_manager/api/graphql_mutations.py
40
40
  src/general_manager/api/graphql_ordering.py
41
41
  src/general_manager/api/graphql_output.py
42
42
  src/general_manager/api/graphql_prefetch.py
43
+ src/general_manager/api/graphql_query_permissions.py
43
44
  src/general_manager/api/graphql_relations.py
44
45
  src/general_manager/api/graphql_resolvers.py
45
46
  src/general_manager/api/graphql_search.py
@@ -36,6 +36,9 @@ import graphene
36
36
  from asgiref.sync import async_to_sync
37
37
  from channels.layers import BaseChannelLayer
38
38
  from django.core.exceptions import ObjectDoesNotExist
39
+
40
+ from general_manager.interface.requests import RequestNotFoundError
41
+ from general_manager.manager.meta import AttributeEvaluationError
39
42
  from django.db import DEFAULT_DB_ALIAS, models, transaction
40
43
  from django.utils.module_loading import import_string
41
44
 
@@ -120,6 +123,7 @@ from general_manager.api.graphql_resolvers import (
120
123
  check_read_permission as _check_read_permission_fn,
121
124
  check_read_permission_for_user as _check_read_permission_for_user_fn,
122
125
  can_read_instance_for_user as _can_read_instance_for_user_fn,
126
+ can_read_class_for_user as _can_read_class_for_user_fn,
123
127
  create_measurement_resolver as _create_measurement_resolver_fn,
124
128
  create_normal_resolver as _create_normal_resolver_fn,
125
129
  create_list_resolver as _create_list_resolver_fn,
@@ -2260,17 +2264,32 @@ class GraphQL:
2260
2264
 
2261
2265
  def resolver(
2262
2266
  self: GeneralManager, info: GraphQLResolveInfo, **identification: object
2263
- ) -> GeneralManager:
2267
+ ) -> GeneralManager | None:
2264
2268
  """
2265
- Instantiate and return a GeneralManager for the provided identification arguments.
2269
+ Instantiate and authorize a manager before exposing its existence.
2266
2270
 
2267
2271
  Parameters:
2268
2272
  identification (dict): Mapping of identification argument names to values passed to the manager constructor.
2269
2273
 
2270
2274
  Returns:
2271
- GeneralManager: The manager instance identified by the provided arguments.
2275
+ GeneralManager | None: The readable manager, or None for missing
2276
+ or unreadable targets.
2272
2277
  """
2273
- return generalManagerClass(**identification)
2278
+ try:
2279
+ instance = generalManagerClass(**identification)
2280
+ except (ObjectDoesNotExist, RequestNotFoundError):
2281
+ # Missing and unreadable targets share the same public response.
2282
+ return None
2283
+ try:
2284
+ readable = _can_read_instance_for_user_fn(instance, info.context.user)
2285
+ except RequestNotFoundError:
2286
+ return None
2287
+ except AttributeEvaluationError as error:
2288
+ # Request-backed fields hydrate lazily during the row gate.
2289
+ if isinstance(error.__cause__, RequestNotFoundError):
2290
+ return None
2291
+ raise
2292
+ return instance if readable else None
2274
2293
 
2275
2294
  cls._query_fields[item_field_name] = item_field
2276
2295
  cls._query_fields[f"resolve_{item_field_name}"] = resolver
@@ -2658,6 +2677,12 @@ class GraphQL:
2658
2677
  continue
2659
2678
  identification = message.get("identification")
2660
2679
  if action == "refresh" and identification is None:
2680
+ if not await asyncio.to_thread(
2681
+ _can_read_class_for_user_fn,
2682
+ generalManagerClass,
2683
+ subscription_user,
2684
+ ):
2685
+ continue
2661
2686
  clear_capability_context(info)
2662
2687
  yield SubscriptionEvent(item=None, action=action)
2663
2688
  continue
@@ -0,0 +1,168 @@
1
+ """Authorize query operands before they influence membership or ordering."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+ from typing import TYPE_CHECKING
7
+
8
+ from graphql import GraphQLError
9
+
10
+ from general_manager.bucket.base_bucket import Bucket
11
+ from general_manager.bucket.request_bucket import RequestBucket
12
+ from general_manager.manager.general_manager import GeneralManager
13
+
14
+ if TYPE_CHECKING:
15
+ from graphene import ResolveInfo
16
+
17
+
18
+ class QueryFieldPermissionError(GraphQLError):
19
+ """A requested operand is not authorized on the candidate scope."""
20
+
21
+ def __init__(self, field: str) -> None:
22
+ super().__init__(f"Permission denied to use query field '{field}'.")
23
+
24
+
25
+ _LIMIT_ERROR = "Query field authorization candidate limit exceeded."
26
+ _AMBIGUOUS_ERROR = "Cannot authorize ambiguous query relation."
27
+ _RELATION_ERROR = "Permission denied to traverse query relation."
28
+ INCOMPLETE_ERROR = "Query field authorization requires a complete candidate set."
29
+ CUSTOM_PROJECTION_ERROR = (
30
+ "Cannot authorize fields of a custom search document projection."
31
+ )
32
+
33
+ # Bound field/path decisions; bucket materialization and row checks precede this.
34
+ MAX_QUERY_PERMISSION_CANDIDATES = 1000
35
+ _LOOKUPS = {
36
+ "exact",
37
+ "iexact",
38
+ "in",
39
+ "isnull",
40
+ "lt",
41
+ "lte",
42
+ "gt",
43
+ "gte",
44
+ "contains",
45
+ "icontains",
46
+ "startswith",
47
+ "istartswith",
48
+ "endswith",
49
+ "iendswith",
50
+ "range",
51
+ }
52
+
53
+
54
+ def authorize_query_fields(
55
+ candidates: Iterable[GeneralManager], info: ResolveInfo, paths: Iterable[str]
56
+ ) -> None:
57
+ """Check all operands against every row-visible candidate, never just hits.
58
+
59
+ Related rows require their own row permission as well as field permission.
60
+ Failure leaves the original candidate set unchanged and rejects the query.
61
+ """
62
+ from general_manager.api.graphql_relations import (
63
+ resolve_general_manager_type,
64
+ get_graphql_manager_registry,
65
+ )
66
+ from general_manager.api.graphql_resolvers import (
67
+ can_read_instance,
68
+ check_read_permission,
69
+ relation_id_alias_field,
70
+ )
71
+
72
+ normalized = set()
73
+ for path in paths:
74
+ parts = path.split("__")
75
+ if parts:
76
+ normalized.add(tuple(parts))
77
+ if not normalized:
78
+ return
79
+ decisions = 0
80
+
81
+ def check(instance: GeneralManager, parts: tuple[str, ...]) -> None:
82
+ nonlocal decisions
83
+ decisions += 1
84
+ if decisions > MAX_QUERY_PERMISSION_CANDIDATES:
85
+ raise GraphQLError(_LIMIT_ERROR)
86
+ field, *rest = parts
87
+ attributes = instance.Interface.get_attribute_types()
88
+ # Backend collection lookup names can differ from public manager names.
89
+ aliases = [
90
+ name
91
+ for name, metadata in attributes.items()
92
+ if metadata.get("filter_lookup", name) == field
93
+ ]
94
+ names = set(aliases or [field])
95
+ for name in tuple(names):
96
+ relation = relation_id_alias_field(type(instance), name)
97
+ if relation is None and name.endswith("_id"):
98
+ alias = name.removesuffix("_id")
99
+ metadata: dict[str, object] = dict(attributes.get(alias, {}))
100
+ if (
101
+ resolve_general_manager_type(
102
+ metadata.get("type"), get_graphql_manager_registry()
103
+ )
104
+ is not None
105
+ ):
106
+ relation = alias
107
+ if relation is not None:
108
+ names.add(relation)
109
+ known_fields = set(attributes) | set(instance.identification)
110
+ known_fields.update(instance.Interface.get_graph_ql_properties())
111
+ known_fields.update(instance.Interface.get_attributes())
112
+ if not names.intersection(known_fields):
113
+ raise QueryFieldPermissionError(field)
114
+ if any(not check_read_permission(instance, info, name) for name in names):
115
+ raise QueryFieldPermissionError(field)
116
+ if not rest:
117
+ return
118
+ if len(aliases) > 1:
119
+ raise GraphQLError(_AMBIGUOUS_ERROR)
120
+ field_metadata: dict[str, object] = dict(
121
+ attributes.get(aliases[0] if aliases else field, {})
122
+ )
123
+ if (
124
+ len(rest) == 1
125
+ and rest[0] in _LOOKUPS
126
+ and (
127
+ (field.endswith("_id") and len(names) > 1)
128
+ or (
129
+ field_metadata.get("type") is not None
130
+ and resolve_general_manager_type(
131
+ field_metadata.get("type"), get_graphql_manager_registry()
132
+ )
133
+ is None
134
+ and field_metadata.get("relation_kind")
135
+ not in {"direct", "collection"}
136
+ )
137
+ )
138
+ ):
139
+ return
140
+ related_type = resolve_general_manager_type(
141
+ field_metadata.get("type"), get_graphql_manager_registry()
142
+ )
143
+ if len(rest) == 1 and rest[0] in _LOOKUPS and related_type is not None:
144
+ related_fields = set(related_type.Interface.get_attribute_types())
145
+ related_fields.update(related_type.Interface.get_attributes())
146
+ related_fields.update(related_type.Interface.get_graph_ql_properties())
147
+ if rest[0] not in related_fields:
148
+ return
149
+ value = getattr(instance, aliases[0] if aliases else field)
150
+ if value is None:
151
+ return
152
+ related = value if isinstance(value, (Bucket, list, tuple, set)) else [value]
153
+ for member in related:
154
+ if not isinstance(member, GeneralManager):
155
+ # A lookup is an operator only after resolving its preceding
156
+ # scalar field. A relation's field named "contains" is a field.
157
+ if len(rest) == 1 and rest[0] in _LOOKUPS:
158
+ continue
159
+ raise GraphQLError(_RELATION_ERROR)
160
+ if not can_read_instance(member, info):
161
+ raise GraphQLError(_RELATION_ERROR)
162
+ check(member, tuple(rest))
163
+
164
+ for candidate in candidates:
165
+ for normalized_parts in sorted(normalized):
166
+ check(candidate, normalized_parts)
167
+ if isinstance(candidates, RequestBucket) and not candidates.response_is_complete:
168
+ raise GraphQLError(INCOMPLETE_ERROR)
@@ -36,6 +36,7 @@ from graphql import GraphQLError, OperationType
36
36
  from graphql.language.ast import FieldNode, FragmentSpreadNode, InlineFragmentNode
37
37
 
38
38
  from general_manager.logging import get_logger
39
+ from general_manager.conf import get_setting
39
40
  from general_manager.bucket.base_bucket import Bucket
40
41
  from general_manager.bucket._materialized_bucket import MaterializedBucket
41
42
  from general_manager.bucket.group_bucket import GroupBucket
@@ -822,6 +823,38 @@ class InvalidPaginationValueError(ValueError):
822
823
  super().__init__(f"{field_name} must be a positive integer")
823
824
 
824
825
 
826
+ class PaginationLimitExceededError(ValueError):
827
+ """Raised when an explicit page exceeds the server maximum."""
828
+
829
+ def __init__(self, maximum: int) -> None:
830
+ super().__init__(f"pageSize must not exceed {maximum}")
831
+
832
+
833
+ class InvalidPaginationConfigurationError(ValueError):
834
+ """Raised when configured pagination cannot provide finite valid pages."""
835
+
836
+ def __init__(self, setting: str) -> None:
837
+ super().__init__(
838
+ f"{setting} must be a positive integer, with default <= maximum"
839
+ )
840
+
841
+
842
+ def _pagination_sizes() -> tuple[int, int]:
843
+ default = get_setting("GRAPHQL_DEFAULT_PAGE_SIZE", 10)
844
+ maximum = get_setting("GRAPHQL_MAX_PAGE_SIZE", 100)
845
+ for name, value in (
846
+ ("GRAPHQL_DEFAULT_PAGE_SIZE", default),
847
+ ("GRAPHQL_MAX_PAGE_SIZE", maximum),
848
+ ):
849
+ if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
850
+ raise InvalidPaginationConfigurationError(name)
851
+ default = cast(int, default)
852
+ maximum = cast(int, maximum)
853
+ if default > maximum:
854
+ raise InvalidPaginationConfigurationError("GRAPHQL_DEFAULT_PAGE_SIZE")
855
+ return default, maximum
856
+
857
+
825
858
  @dataclass(frozen=True, slots=True)
826
859
  class EffectivePagination:
827
860
  """Normalized public pagination arguments and their observable defaults."""
@@ -849,19 +882,19 @@ def normalize_pagination(
849
882
  page: int | None,
850
883
  page_size: int | None,
851
884
  ) -> EffectivePagination:
852
- """Normalize list pagination once, preserving the unpaginated no-arg mode."""
853
- requested = page is not None or page_size is not None
885
+ """Resolve finite server defaults and reject oversized explicit pages."""
886
+ default, maximum = _pagination_sizes()
854
887
  for field_name, value in (("page", page), ("pageSize", page_size)):
855
888
  if value is not None and (
856
889
  not isinstance(value, int) or isinstance(value, bool) or value <= 0
857
890
  ):
858
891
  raise InvalidPaginationValueError(field_name)
859
- if not requested:
860
- return EffectivePagination(requested=False, page=1, page_size=None)
892
+ if page_size is not None and page_size > maximum:
893
+ raise PaginationLimitExceededError(maximum)
861
894
  return EffectivePagination(
862
895
  requested=True,
863
896
  page=1 if page is None else page,
864
- page_size=10 if page_size is None else page_size,
897
+ page_size=default if page_size is None else page_size,
865
898
  )
866
899
 
867
900
 
@@ -922,6 +955,9 @@ def _forward_remote_request_controls(
922
955
  terms = order_by_to_sort_terms(order_by)
923
956
  except GraphQLOrderingInputError as exc:
924
957
  raise GraphQLError(str(exc)) from exc
958
+ if not isinstance(queryset, RequestBucket) or queryset.request_plan is None:
959
+ # Concrete snapshots must be paginated locally, never filtered by controls.
960
+ return queryset, False
925
961
  controls: dict[str, object] = {}
926
962
  if pagination.requested:
927
963
  controls["page"] = pagination.page
@@ -943,8 +979,8 @@ def apply_pagination(
943
979
  """
944
980
  Return a paginated slice of *queryset*.
945
981
 
946
- Returns the full queryset when neither ``page`` nor ``page_size`` is
947
- given. Defaults to page 1 / size 10 when only one parameter is provided.
982
+ Omitted controls use page 1 and the configured finite default size (10).
983
+ Explicit sizes above the configured maximum (100) are rejected.
948
984
  Zero, negative, boolean, and non-integer controls raise ``ValueError``
949
985
  before slicing.
950
986
  Already-empty grouped buckets are returned unchanged when pagination is
@@ -1268,6 +1304,34 @@ def _is_supported_grouped_annotation(
1268
1304
  )
1269
1305
 
1270
1306
 
1307
+ def can_read_class_for_user(
1308
+ manager_class: type[GeneralManager],
1309
+ user: object,
1310
+ ) -> bool:
1311
+ """Authorize an identity-less notification through the class read gate.
1312
+
1313
+ Construct fresh permissions for every event so revocations take effect.
1314
+ Callers in async code must offload this potentially database-backed check.
1315
+ """
1316
+ from django.contrib.auth import get_user_model
1317
+
1318
+ user_model = get_user_model()
1319
+ if isinstance(user, user_model):
1320
+ if user.pk is None:
1321
+ return False
1322
+ user = (
1323
+ user_model._default_manager.using(user._state.db).filter(pk=user.pk).first()
1324
+ )
1325
+ if user is None or not getattr(user, "is_active", True):
1326
+ return False
1327
+ permission_class: type[BasePermission] | None = getattr(
1328
+ manager_class, "Permission", None
1329
+ )
1330
+ if permission_class is not None:
1331
+ return permission_class(manager_class, user).check_operation_permission("read")
1332
+ return True
1333
+
1334
+
1271
1335
  def can_read_instance_for_user(
1272
1336
  instance: GeneralManager,
1273
1337
  user: object,
@@ -1560,9 +1624,8 @@ def create_list_resolver(
1560
1624
  ``pageInfo`` contains ``total_count``, ``page_size``,
1561
1625
  ``current_page``, and ``total_pages`` using the Python-side field names;
1562
1626
  Graphene exposes them as camelCase in the GraphQL schema. ``current_page``
1563
- reports effective pagination values: supplied single controls default
1564
- the missing coordinate to page 1 / size 10, while ordinary no-argument
1565
- lists remain unpaginated with ``page_size=None``. ``total_pages`` is
1627
+ reports effective pagination values: omitted controls default to page 1
1628
+ and the server-configured finite page size (10 by default). ``total_pages`` is
1566
1629
  zero for an exact empty result and ``None`` when the source total is
1567
1630
  incomplete. Invalid pagination values raise
1568
1631
  ``InvalidPaginationValueError`` before slicing.
@@ -1579,6 +1642,7 @@ def create_list_resolver(
1579
1642
  group_by: list[str] | None = None,
1580
1643
  include_inactive: bool = False,
1581
1644
  ) -> ListResolverPayload:
1645
+ effective_pagination = normalize_pagination(page, page_size)
1582
1646
  _ensure_as_of_compatible(self)
1583
1647
  base_queryset = base_getter(self, include_inactive)
1584
1648
  if base_queryset is None:
@@ -1606,7 +1670,12 @@ def create_list_resolver(
1606
1670
  exclude,
1607
1671
  filter_normalizer=bound_filter_normalizer,
1608
1672
  )
1609
- effective_pagination = normalize_pagination(page, page_size)
1673
+ from general_manager.api.graphql_query_permissions import authorize_query_fields
1674
+
1675
+ operand_paths = (
1676
+ set(plan.filters) | set(plan.excludes) | set(plan.normalized_excludes)
1677
+ )
1678
+ operand_paths.update(term.field for term in order_by_to_sort_terms(order_by))
1610
1679
  from general_manager.interface import CalculationInterface
1611
1680
 
1612
1681
  interface = getattr(manager_class, "Interface", None)
@@ -1614,30 +1683,105 @@ def create_list_resolver(
1614
1683
  remote_ordering_forwarded = False
1615
1684
  request_provenance: RequestPaginationProvenance | None = None
1616
1685
  authorization_result: ReadAuthorizationResult[GeneralManager]
1617
- if isinstance(interface, type) and issubclass(interface, CalculationInterface):
1618
- input_plan, deferred_plan = partition_calculation_query_plan(
1619
- manager_class,
1620
- plan,
1621
- )
1622
- input_queryset = apply_query_parameter_plan(
1623
- base_queryset,
1624
- input_plan,
1625
- None,
1686
+ complete_disjunction: ReadAuthorizationPreparation[GeneralManager] | None = None
1687
+ if is_request_source and not operand_paths:
1688
+ request_permission_plan = get_read_permission_filter(manager_class, info)
1689
+ if (
1690
+ request_permission_plan.decision != "deny_all"
1691
+ and len(request_permission_plan.filters) > 1
1692
+ ):
1693
+ # Check completeness before RequestBucket union loses provenance.
1694
+ # No client predicates are evaluated on this local union.
1695
+ combined = MaterializedBucket(manager_class, [])
1696
+ for permission_filter in request_permission_plan.filters:
1697
+ branch = base_queryset.filter(
1698
+ **permission_filter.get("filter", {})
1699
+ ).exclude(**permission_filter.get("exclude", {}))
1700
+ if (
1701
+ isinstance(branch, RequestBucket)
1702
+ and not branch.response_is_complete
1703
+ ):
1704
+ operation = _requested_request_global_operation(
1705
+ effective_pagination, group_by, order_by
1706
+ )
1707
+ raise _request_global_operation_error(operation or "pagination")
1708
+ combined = combined | MaterializedBucket(manager_class, branch)
1709
+ shape = get_backend_shape(manager_class)
1710
+ complete_disjunction = ReadAuthorizationPreparation(
1711
+ queryset=combined,
1712
+ permission_plan=request_permission_plan,
1713
+ backend_shape=shape,
1714
+ instance_check_reasons=resolve_instance_check_reasons(
1715
+ request_permission_plan, backend_shape=shape
1716
+ ),
1717
+ )
1718
+ if operand_paths and is_request_source:
1719
+ operand_preparation = prepare_read_authorization(
1720
+ base_queryset, manager_class, info
1626
1721
  )
1722
+ # Inspect the permission-filtered source before a final instance
1723
+ # gate can materialize it and discard upstream provenance. Never
1724
+ # touch the original source when the plan denies all rows.
1627
1725
  if (
1628
- input_plan.filters
1629
- or input_plan.excludes
1630
- or input_plan.normalized_excludes
1726
+ operand_preparation.permission_plan.decision != "deny_all"
1727
+ and isinstance(operand_preparation.queryset, RequestBucket)
1728
+ and not operand_preparation.queryset.response_is_complete
1631
1729
  ):
1632
- input_queryset = input_queryset.with_instances(input_queryset)
1730
+ from general_manager.api.graphql_query_permissions import (
1731
+ INCOMPLETE_ERROR,
1732
+ )
1733
+
1734
+ raise GraphQLError(INCOMPLETE_ERROR)
1735
+ operand_candidates = finalize_read_authorization(
1736
+ operand_preparation, manager_class, info, source="query_fields"
1737
+ ).queryset
1738
+ authorize_query_fields(operand_candidates, info, operand_paths)
1739
+ if isinstance(interface, type) and issubclass(interface, CalculationInterface):
1633
1740
  authorization_result = apply_read_authorization(
1634
- input_queryset,
1635
- manager_class,
1636
- info,
1637
- source="list",
1741
+ base_queryset, manager_class, info, source="list"
1638
1742
  )
1639
1743
  qs = authorization_result.queryset
1744
+ authorize_query_fields(qs, info, operand_paths)
1745
+ # Freeze row authorization before constructor-input filters can
1746
+ # replace the calculation bucket's permission constraints.
1747
+ if operand_paths:
1748
+ qs = qs.with_instances(qs)
1749
+ input_plan, deferred_plan = partition_calculation_query_plan(
1750
+ manager_class, plan
1751
+ )
1752
+
1753
+ def canonical_inputs(mapping: GraphQLFilterMapping) -> GraphQLFilterMapping:
1754
+ normalized = {}
1755
+ for lookup, value in mapping.items():
1756
+ root, separator, suffix = lookup.partition("__")
1757
+ alias = (
1758
+ interface.input_fields.get(root.removesuffix("_id"))
1759
+ if root.endswith("_id")
1760
+ else None
1761
+ )
1762
+ if alias is not None and safe_issubclass(
1763
+ alias.type, GeneralManager
1764
+ ):
1765
+ lookup = (
1766
+ root.removesuffix("_id")
1767
+ + "__id"
1768
+ + (separator + suffix if separator else "")
1769
+ )
1770
+ normalized[lookup] = value
1771
+ return normalized
1772
+
1773
+ input_plan = QueryParameterPlan(
1774
+ canonical_inputs(input_plan.filters),
1775
+ canonical_inputs(input_plan.excludes),
1776
+ canonical_inputs(input_plan.normalized_excludes),
1777
+ )
1778
+ qs = apply_query_parameter_plan(qs, input_plan, None)
1640
1779
  qs = apply_query_parameter_plan(qs, deferred_plan, None)
1780
+ elif complete_disjunction is not None:
1781
+ authorization_result = finalize_read_authorization(
1782
+ complete_disjunction, manager_class, info, source="list"
1783
+ )
1784
+ qs = authorization_result.queryset
1641
1785
  elif is_request_source:
1642
1786
  permission_plan = get_read_permission_filter(manager_class, info)
1643
1787
  if permission_plan.decision == "deny_all":
@@ -1692,12 +1836,6 @@ def create_list_resolver(
1692
1836
  )
1693
1837
  assert request_provenance is not None
1694
1838
  if request_provenance.is_partial:
1695
- if effective_pagination.requested and (
1696
- request_provenance.page != effective_pagination.page
1697
- or request_provenance.page_size
1698
- != effective_pagination.page_size
1699
- ):
1700
- raise _request_global_operation_error("pagination")
1701
1839
  if group_by is not None:
1702
1840
  raise _request_global_operation_error("grouping")
1703
1841
  if order_by is not None and not remote_ordering_forwarded:
@@ -1707,6 +1845,12 @@ def create_list_resolver(
1707
1845
  raise GraphQLError(str(exc)) from exc
1708
1846
  if has_ordering:
1709
1847
  raise _request_global_operation_error("ordering")
1848
+ if effective_pagination.requested and (
1849
+ request_provenance.page != effective_pagination.page
1850
+ or request_provenance.page_size
1851
+ != effective_pagination.page_size
1852
+ ):
1853
+ raise _request_global_operation_error("pagination")
1710
1854
  authorization_result = finalize_read_authorization(
1711
1855
  authorization_preparation,
1712
1856
  manager_class,
@@ -1732,6 +1876,7 @@ def create_list_resolver(
1732
1876
  source="list",
1733
1877
  )
1734
1878
  qs = authorization_result.queryset
1879
+ authorize_query_fields(qs, info, operand_paths)
1735
1880
  qs = apply_query_parameter_plan(qs, plan, None)
1736
1881
  if grouping_validator is not None:
1737
1882
  grouping_validator(qs, group_by, order_by, info)
@@ -1751,16 +1896,6 @@ def create_list_resolver(
1751
1896
  total_count = request_provenance.total_count
1752
1897
 
1753
1898
  metadata_pagination = effective_pagination
1754
- if (
1755
- not effective_pagination.requested
1756
- and request_provenance is not None
1757
- and request_provenance.page is not None
1758
- ):
1759
- metadata_pagination = EffectivePagination(
1760
- requested=True,
1761
- page=request_provenance.page,
1762
- page_size=request_provenance.page_size,
1763
- )
1764
1899
 
1765
1900
  upstream_page_matches = (
1766
1901
  request_provenance is not None
@@ -1770,7 +1905,7 @@ def create_list_resolver(
1770
1905
  and group_by is None
1771
1906
  )
1772
1907
  qs_paginated = (
1773
- qs_sorted
1908
+ qs_sorted[: cast(int, metadata_pagination.page_size)]
1774
1909
  if upstream_page_matches
1775
1910
  else apply_pagination(
1776
1911
  qs_sorted,