scalekit-sdk-python 2.21.0__tar.gz → 2.23.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 (329) hide show
  1. {scalekit_sdk_python-2.21.0/scalekit_sdk_python.egg-info → scalekit_sdk_python-2.23.0}/PKG-INFO +3 -2
  2. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/README.md +1 -1
  3. scalekit_sdk_python-2.23.0/scalekit/__init__.py +22 -0
  4. scalekit_sdk_python-2.23.0/scalekit/_convert.py +163 -0
  5. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/_version.py +1 -1
  6. scalekit_sdk_python-2.23.0/scalekit/actions/__init__.py +112 -0
  7. scalekit_sdk_python-2.23.0/scalekit/actions/_proxy_path.py +254 -0
  8. scalekit_sdk_python-2.23.0/scalekit/actions/_resumable_upload.py +901 -0
  9. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/actions.py +370 -22
  10. scalekit_sdk_python-2.23.0/scalekit/actions/connections/__init__.py +26 -0
  11. scalekit_sdk_python-2.23.0/scalekit/actions/connections/errors.py +148 -0
  12. scalekit_sdk_python-2.23.0/scalekit/actions/connections/models.py +257 -0
  13. scalekit_sdk_python-2.23.0/scalekit/actions/connections/service.py +352 -0
  14. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/custom_provider.py +20 -0
  15. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/mcp_config.py +34 -0
  16. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/list_providers_request.py +3 -2
  17. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/get_connected_account_auth_response.py +5 -1
  18. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/list_connected_accounts_response.py +20 -2
  19. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/list_providers_response.py +11 -1
  20. scalekit_sdk_python-2.23.0/scalekit/actions/models/trigger_event.py +192 -0
  21. scalekit_sdk_python-2.23.0/scalekit/actions/models/triggers.py +1247 -0
  22. scalekit_sdk_python-2.23.0/scalekit/actions/models/upload_progress.py +32 -0
  23. scalekit_sdk_python-2.23.0/scalekit/actions/triggers.py +1052 -0
  24. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/types.py +100 -0
  25. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/client.py +25 -59
  26. scalekit_sdk_python-2.23.0/scalekit/common/_webhook_signature.py +165 -0
  27. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/common/exceptions.py +106 -2
  28. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/connected_accounts.py +18 -0
  29. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/core.py +1 -1
  30. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/mcp.py +6 -1
  31. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/providers.py +3 -1
  32. scalekit_sdk_python-2.23.0/scalekit/triggers.py +390 -0
  33. scalekit_sdk_python-2.23.0/scalekit/v1/billing/billing_pb2.py +277 -0
  34. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/billing/billing_pb2.pyi +253 -4
  35. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/billing/billing_pb2_grpc.py +217 -0
  36. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/clients/clients_pb2.py +214 -208
  37. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/clients/clients_pb2.pyi +12 -6
  38. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/commons/commons_pb2.py +6 -6
  39. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/commons/commons_pb2.pyi +2 -0
  40. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.py +71 -57
  41. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi +16 -0
  42. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py +34 -0
  43. scalekit_sdk_python-2.23.0/scalekit/v1/connections/connections_pb2.py +920 -0
  44. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/connections/connections_pb2.pyi +222 -2
  45. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/connections/connections_pb2_grpc.py +132 -0
  46. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/events/events_pb2.py +8 -8
  47. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/events/events_pb2.pyi +2 -0
  48. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/mcp/mcp_pb2.py +74 -68
  49. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/mcp/mcp_pb2.pyi +18 -4
  50. scalekit_sdk_python-2.23.0/scalekit/v1/providers/providers_pb2.py +282 -0
  51. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/providers/providers_pb2.pyi +54 -6
  52. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/providers/providers_pb2_grpc.py +67 -0
  53. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tools/tools_pb2.py +42 -40
  54. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tools/tools_pb2.pyi +4 -2
  55. scalekit_sdk_python-2.23.0/scalekit/v1/triggers/triggers_pb2.py +642 -0
  56. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/triggers/triggers_pb2.pyi +360 -4
  57. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/triggers/triggers_pb2_grpc.py +303 -1
  58. scalekit_sdk_python-2.23.0/scalekit/v1/workspaces/workspaces_pb2.py +279 -0
  59. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/workspaces/workspaces_pb2.pyi +4 -2
  60. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0/scalekit_sdk_python.egg-info}/PKG-INFO +3 -2
  61. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit_sdk_python.egg-info/SOURCES.txt +23 -0
  62. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit_sdk_python.egg-info/requires.txt +1 -0
  63. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/setup.py +1 -0
  64. scalekit_sdk_python-2.23.0/tests/test_actions_request_path.py +555 -0
  65. scalekit_sdk_python-2.23.0/tests/test_actions_response_fields.py +118 -0
  66. scalekit_sdk_python-2.23.0/tests/test_agentkit_connections.py +217 -0
  67. scalekit_sdk_python-2.23.0/tests/test_list_connected_accounts_query_and_org_wide.py +78 -0
  68. scalekit_sdk_python-2.23.0/tests/test_mcp_tool_exposure.py +34 -0
  69. scalekit_sdk_python-2.23.0/tests/test_resumable_upload.py +1325 -0
  70. scalekit_sdk_python-2.23.0/tests/test_resumable_upload_live.py +214 -0
  71. scalekit_sdk_python-2.23.0/tests/test_trigger_events.py +1049 -0
  72. scalekit_sdk_python-2.23.0/tests/test_triggers_api.py +1233 -0
  73. scalekit_sdk_python-2.23.0/tests/test_triggers_api_live.py +400 -0
  74. scalekit_sdk_python-2.21.0/scalekit/__init__.py +0 -5
  75. scalekit_sdk_python-2.21.0/scalekit/actions/__init__.py +0 -5
  76. scalekit_sdk_python-2.21.0/scalekit/v1/billing/billing_pb2.py +0 -171
  77. scalekit_sdk_python-2.21.0/scalekit/v1/connections/connections_pb2.py +0 -751
  78. scalekit_sdk_python-2.21.0/scalekit/v1/providers/providers_pb2.py +0 -190
  79. scalekit_sdk_python-2.21.0/scalekit/v1/triggers/triggers_pb2.py +0 -376
  80. scalekit_sdk_python-2.21.0/scalekit/v1/workspaces/workspaces_pb2.py +0 -277
  81. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/LICENSE +0 -0
  82. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/buf/__init__.py +0 -0
  83. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/buf/validate/__init__.py +0 -0
  84. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/buf/validate/validate_pb2.py +0 -0
  85. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/buf/validate/validate_pb2.pyi +0 -0
  86. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/buf/validate/validate_pb2_grpc.py +0 -0
  87. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/pyproject.toml +0 -0
  88. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/frameworks/__init__.py +0 -0
  89. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/frameworks/google_adk.py +0 -0
  90. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/frameworks/langchain.py +0 -0
  91. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/frameworks/types/__init__.py +0 -0
  92. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/frameworks/types/google_adk_tool.py +0 -0
  93. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/frameworks/util.py +0 -0
  94. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/__init__.py +0 -0
  95. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/mcp_connection_auth_state.py +0 -0
  96. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/mcp_instance.py +0 -0
  97. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/__init__.py +0 -0
  98. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/create_connected_account_request.py +0 -0
  99. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/create_custom_provider_request.py +0 -0
  100. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/delete_custom_provider_request.py +0 -0
  101. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/mcp_request.py +0 -0
  102. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/tool_request.py +0 -0
  103. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/update_connected_account_request.py +0 -0
  104. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/requests/update_custom_provider_request.py +0 -0
  105. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/__init__.py +0 -0
  106. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/create_connected_account_response.py +0 -0
  107. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/create_custom_provider_response.py +0 -0
  108. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/create_mcp_config_response.py +0 -0
  109. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/create_mcp_response.py +0 -0
  110. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/create_mcp_session_token_response.py +0 -0
  111. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/delete_connected_account_response.py +0 -0
  112. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/delete_custom_provider_response.py +0 -0
  113. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/delete_mcp_config_response.py +0 -0
  114. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/delete_mcp_instance_response.py +0 -0
  115. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/ensure_mcp_instance_response.py +0 -0
  116. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/execute_tool_response.py +0 -0
  117. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/get_mcp_instance_auth_state_response.py +0 -0
  118. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/get_mcp_instance_response.py +0 -0
  119. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/get_mcp_response.py +0 -0
  120. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/list_mcp_configs_response.py +0 -0
  121. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/list_mcp_connected_accounts_response.py +0 -0
  122. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/list_mcp_instances_response.py +0 -0
  123. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/list_tools_response.py +0 -0
  124. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/magic_link_response.py +0 -0
  125. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/update_connected_account_response.py +0 -0
  126. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/update_custom_provider_response.py +0 -0
  127. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/update_mcp_config_response.py +0 -0
  128. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/update_mcp_instance_response.py +0 -0
  129. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/responses/verify_connected_account_user_response.py +0 -0
  130. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/tool_input_output.py +0 -0
  131. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/models/tool_mapping.py +0 -0
  132. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/actions/modifier.py +0 -0
  133. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/auth.py +0 -0
  134. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/common/__init__.py +0 -0
  135. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/common/scalekit.py +0 -0
  136. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/common/user.py +0 -0
  137. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/connection.py +0 -0
  138. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/constants/__init__.py +0 -0
  139. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/constants/user.py +0 -0
  140. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/directory.py +0 -0
  141. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/domain.py +0 -0
  142. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/events.py +0 -0
  143. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/frameworks/__init__.py +0 -0
  144. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/frameworks/django.py +0 -0
  145. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/frameworks/fastapi.py +0 -0
  146. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/frameworks/flask.py +0 -0
  147. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/m2m_client.py +0 -0
  148. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/middleware/__init__.py +0 -0
  149. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/middleware/csrf_state.py +0 -0
  150. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/middleware/protocol.py +0 -0
  151. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/middleware/session_crypto.py +0 -0
  152. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/middleware/session_manager.py +0 -0
  153. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/organization.py +0 -0
  154. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/passwordless.py +0 -0
  155. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/permissions.py +0 -0
  156. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/resource.py +0 -0
  157. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/role.py +0 -0
  158. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/sessions.py +0 -0
  159. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/token.py +0 -0
  160. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/tools.py +0 -0
  161. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/users.py +0 -0
  162. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/utils/__init__.py +0 -0
  163. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/utils/directory.py +0 -0
  164. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/__init__.py +0 -0
  165. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/agentkit_logs/__init__.py +0 -0
  166. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.py +0 -0
  167. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.pyi +0 -0
  168. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2_grpc.py +0 -0
  169. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2.py +0 -0
  170. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2.pyi +0 -0
  171. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2_grpc.py +0 -0
  172. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auditlogs/__init__.py +0 -0
  173. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auditlogs/auditlogs_pb2.py +0 -0
  174. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auditlogs/auditlogs_pb2.pyi +0 -0
  175. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auditlogs/auditlogs_pb2_grpc.py +0 -0
  176. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/__init__.py +0 -0
  177. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/auth_pb2.py +0 -0
  178. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/auth_pb2.pyi +0 -0
  179. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/auth_pb2_grpc.py +0 -0
  180. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/passwordless_pb2.py +0 -0
  181. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/passwordless_pb2.pyi +0 -0
  182. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/passwordless_pb2_grpc.py +0 -0
  183. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/totp_pb2.py +0 -0
  184. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/totp_pb2.pyi +0 -0
  185. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/totp_pb2_grpc.py +0 -0
  186. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/webauthn_pb2.py +0 -0
  187. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/webauthn_pb2.pyi +0 -0
  188. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/auth/webauthn_pb2_grpc.py +0 -0
  189. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/billing/__init__.py +0 -0
  190. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/clients/__init__.py +0 -0
  191. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/clients/clients_pb2_grpc.py +0 -0
  192. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/commons/__init__.py +0 -0
  193. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/commons/commons_pb2_grpc.py +0 -0
  194. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/connected_accounts/__init__.py +0 -0
  195. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/connections/__init__.py +0 -0
  196. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/directories/__init__.py +0 -0
  197. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/directories/directories_pb2.py +0 -0
  198. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/directories/directories_pb2.pyi +0 -0
  199. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/directories/directories_pb2_grpc.py +0 -0
  200. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/domains/__init__.py +0 -0
  201. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/domains/domains_pb2.py +0 -0
  202. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/domains/domains_pb2.pyi +0 -0
  203. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/domains/domains_pb2_grpc.py +0 -0
  204. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/emails/__init__.py +0 -0
  205. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/emails/emails_pb2.py +0 -0
  206. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/emails/emails_pb2.pyi +0 -0
  207. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/emails/emails_pb2_grpc.py +0 -0
  208. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/environments/__init__.py +0 -0
  209. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/environments/environments_pb2.py +0 -0
  210. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/environments/environments_pb2.pyi +0 -0
  211. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/environments/environments_pb2_grpc.py +0 -0
  212. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/errdetails/__init__.py +0 -0
  213. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/errdetails/errdetails_pb2.py +0 -0
  214. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/errdetails/errdetails_pb2.pyi +0 -0
  215. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/errdetails/errdetails_pb2_grpc.py +0 -0
  216. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/events/__init__.py +0 -0
  217. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/events/events_pb2_grpc.py +0 -0
  218. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/gateway/__init__.py +0 -0
  219. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/gateway/gateway_pb2.py +0 -0
  220. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/gateway/gateway_pb2.pyi +0 -0
  221. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/gateway/gateway_pb2_grpc.py +0 -0
  222. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/interceptors/__init__.py +0 -0
  223. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/interceptors/interceptors_pb2.py +0 -0
  224. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/interceptors/interceptors_pb2.pyi +0 -0
  225. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/interceptors/interceptors_pb2_grpc.py +0 -0
  226. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/keys/__init__.py +0 -0
  227. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/keys/keys_pb2.py +0 -0
  228. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/keys/keys_pb2.pyi +0 -0
  229. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/keys/keys_pb2_grpc.py +0 -0
  230. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/logstreams/__init__.py +0 -0
  231. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/logstreams/logstreams_pb2.py +0 -0
  232. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/logstreams/logstreams_pb2.pyi +0 -0
  233. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/logstreams/logstreams_pb2_grpc.py +0 -0
  234. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/mcp/__init__.py +0 -0
  235. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/mcp/mcp_pb2_grpc.py +0 -0
  236. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/members/__init__.py +0 -0
  237. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/members/members_pb2.py +0 -0
  238. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/members/members_pb2.pyi +0 -0
  239. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/members/members_pb2_grpc.py +0 -0
  240. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/migrations/__init__.py +0 -0
  241. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/migrations/migrations_pb2.py +0 -0
  242. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/migrations/migrations_pb2.pyi +0 -0
  243. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/migrations/migrations_pb2_grpc.py +0 -0
  244. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/options/__init__.py +0 -0
  245. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/options/options_pb2.py +0 -0
  246. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/options/options_pb2.pyi +0 -0
  247. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/options/options_pb2_grpc.py +0 -0
  248. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/organizations/__init__.py +0 -0
  249. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/organizations/organizations_pb2.py +0 -0
  250. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/organizations/organizations_pb2.pyi +0 -0
  251. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/organizations/organizations_pb2_grpc.py +0 -0
  252. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/providers/__init__.py +0 -0
  253. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/roles/__init__.py +0 -0
  254. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/roles/roles_pb2.py +0 -0
  255. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/roles/roles_pb2.pyi +0 -0
  256. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/roles/roles_pb2_grpc.py +0 -0
  257. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/secrets/__init__.py +0 -0
  258. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/secrets/secrets_pb2.py +0 -0
  259. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/secrets/secrets_pb2.pyi +0 -0
  260. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/secrets/secrets_pb2_grpc.py +0 -0
  261. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/sessions/__init__.py +0 -0
  262. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/sessions/sessions_pb2.py +0 -0
  263. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/sessions/sessions_pb2.pyi +0 -0
  264. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/sessions/sessions_pb2_grpc.py +0 -0
  265. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tokens/__init__.py +0 -0
  266. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tokens/tokens_pb2.py +0 -0
  267. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tokens/tokens_pb2.pyi +0 -0
  268. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tokens/tokens_pb2_grpc.py +0 -0
  269. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tools/__init__.py +0 -0
  270. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/tools/tools_pb2_grpc.py +0 -0
  271. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/triggers/__init__.py +0 -0
  272. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/user_attributes/__init__.py +0 -0
  273. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/user_attributes/user_attributes_pb2.py +0 -0
  274. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/user_attributes/user_attributes_pb2.pyi +0 -0
  275. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/user_attributes/user_attributes_pb2_grpc.py +0 -0
  276. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/users/__init__.py +0 -0
  277. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/users/users_pb2.py +0 -0
  278. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/users/users_pb2.pyi +0 -0
  279. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/users/users_pb2_grpc.py +0 -0
  280. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/webhooks/__init__.py +0 -0
  281. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/webhooks/webhooks_pb2.py +0 -0
  282. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/webhooks/webhooks_pb2.pyi +0 -0
  283. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/webhooks/webhooks_pb2_grpc.py +0 -0
  284. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/workspaces/__init__.py +0 -0
  285. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/v1/workspaces/workspaces_pb2_grpc.py +0 -0
  286. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit/webauthn.py +0 -0
  287. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit_sdk_python.egg-info/dependency_links.txt +0 -0
  288. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/scalekit_sdk_python.egg-info/top_level.txt +0 -0
  289. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/setup.cfg +0 -0
  290. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_actions.py +0 -0
  291. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_actions_list_connected_accounts_pagination.py +0 -0
  292. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_call_timeout.py +0 -0
  293. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_connected_accounts.py +0 -0
  294. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_connection.py +0 -0
  295. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_directory.py +0 -0
  296. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_domain.py +0 -0
  297. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_events.py +0 -0
  298. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_http_timeout.py +0 -0
  299. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_keepalive_channel_options.py +0 -0
  300. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_login.py +0 -0
  301. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_m2m_client.py +0 -0
  302. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_mcp.py +0 -0
  303. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_mcp_connection_session_token.py +0 -0
  304. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_mcp_session_token_access_level.py +0 -0
  305. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_middleware_csrf_state.py +0 -0
  306. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_middleware_django.py +0 -0
  307. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_middleware_fastapi.py +0 -0
  308. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_middleware_flask.py +0 -0
  309. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_middleware_session_crypto.py +0 -0
  310. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_middleware_session_manager.py +0 -0
  311. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_multi_issuer.py +0 -0
  312. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_org_roles.py +0 -0
  313. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_organization.py +0 -0
  314. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_organization_session_policy.py +0 -0
  315. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_organization_slug_logo.py +0 -0
  316. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_passwordless.py +0 -0
  317. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_permissions.py +0 -0
  318. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_providers.py +0 -0
  319. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_resource.py +0 -0
  320. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_role_defaults_dependent.py +0 -0
  321. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_roles.py +0 -0
  322. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_sessions.py +0 -0
  323. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_sk819_retry_behavior.py +0 -0
  324. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_tokens.py +0 -0
  325. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_tools.py +0 -0
  326. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_transient_error_no_retry.py +0 -0
  327. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_user_roles_permissions.py +0 -0
  328. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_users.py +0 -0
  329. {scalekit_sdk_python-2.21.0 → scalekit_sdk_python-2.23.0}/tests/test_webauthn_credentials.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scalekit-sdk-python
3
- Version: 2.21.0
3
+ Version: 2.23.0
4
4
  Summary: Scalekit official Python SDK
5
5
  Home-page: https://github.com/scalekit-inc/scalekit-sdk-python
6
6
  Author: Team Scalekit
@@ -15,6 +15,7 @@ Requires-Dist: grpcio<2.0,>=1.81.0
15
15
  Requires-Dist: protobuf<8.0.0,>=5.29.5
16
16
  Requires-Dist: google>=3.0
17
17
  Requires-Dist: requests>=2.34.0
18
+ Requires-Dist: urllib3<3,>=1.26
18
19
  Requires-Dist: PyJWT>=2.13.0
19
20
  Requires-Dist: cffi>=1.15.1
20
21
  Requires-Dist: cryptography>=50.0.0
@@ -60,7 +61,7 @@ Dynamic: summary
60
61
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
61
62
  [![Python versions](https://img.shields.io/pypi/pyversions/scalekit-sdk-python.svg?style=flat-square)](https://pypi.org/project/scalekit-sdk-python/)
62
63
 
63
- <a href="https://scalekit.com" target="_blank" rel="noopener noreferrer">Scalekit</a> provides auth and actions on behalf of users, with 500+ connectors and 20,000+ tools. Build secure AI products faster with authentication for humans (SSO, passwordless, full-stack auth) and agents (MCP/APIs, delegated actions), all unified on one platform. This Python SDK enables both traditional B2B authentication and cutting-edge agentic workflows.
64
+ <a href="https://scalekit.com" target="_blank" rel="noopener noreferrer">Scalekit</a> provides auth and actions on behalf of users, with 600+ connectors and 35,000+ tools. Build secure AI products faster with authentication for humans (SSO, passwordless, full-stack auth) and agents (MCP/APIs, delegated actions), all unified on one platform. This Python SDK enables both traditional B2B authentication and cutting-edge agentic workflows.
64
65
 
65
66
  ## 🤖 Agent-First Features
66
67
 
@@ -13,7 +13,7 @@
13
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
14
  [![Python versions](https://img.shields.io/pypi/pyversions/scalekit-sdk-python.svg?style=flat-square)](https://pypi.org/project/scalekit-sdk-python/)
15
15
 
16
- <a href="https://scalekit.com" target="_blank" rel="noopener noreferrer">Scalekit</a> provides auth and actions on behalf of users, with 500+ connectors and 20,000+ tools. Build secure AI products faster with authentication for humans (SSO, passwordless, full-stack auth) and agents (MCP/APIs, delegated actions), all unified on one platform. This Python SDK enables both traditional B2B authentication and cutting-edge agentic workflows.
16
+ <a href="https://scalekit.com" target="_blank" rel="noopener noreferrer">Scalekit</a> provides auth and actions on behalf of users, with 600+ connectors and 35,000+ tools. Build secure AI products faster with authentication for humans (SSO, passwordless, full-stack auth) and agents (MCP/APIs, delegated actions), all unified on one platform. This Python SDK enables both traditional B2B authentication and cutting-edge agentic workflows.
17
17
 
18
18
  ## 🤖 Agent-First Features
19
19
 
@@ -0,0 +1,22 @@
1
+
2
+ from scalekit.client import ScalekitClient
3
+ from scalekit.common.scalekit import CodeAuthenticationOptions, AuthorizationUrlOptions
4
+ from scalekit.actions.models.trigger_event import (
5
+ DeliveryScope,
6
+ DetectionMode,
7
+ PayloadState,
8
+ TriggerEvent,
9
+ )
10
+ from scalekit.actions.triggers import HeadersLike, verify_trigger_event
11
+
12
+ __all__ = [
13
+ 'ScalekitClient',
14
+ 'AuthorizationUrlOptions',
15
+ 'CodeAuthenticationOptions',
16
+ 'DeliveryScope',
17
+ 'DetectionMode',
18
+ 'HeadersLike',
19
+ 'PayloadState',
20
+ 'TriggerEvent',
21
+ 'verify_trigger_event',
22
+ ]
@@ -0,0 +1,163 @@
1
+ """Private converters between protobuf values and SDK types.
2
+
3
+ One place for the rules every SDK-owned model follows: timestamps are read only when
4
+ the field is present and come out as timezone-aware UTC ``datetime``; inputs must be
5
+ timezone-aware; enum values the SDK does not know never raise; durations are
6
+ ``timedelta``. Nothing here imports the rest of the SDK, so any module can use it.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import re
12
+ from collections.abc import Sequence
13
+ from datetime import date, datetime, timedelta, timezone
14
+ from enum import Enum
15
+ from typing import TypeVar
16
+
17
+ from google.protobuf.internal.enum_type_wrapper import EnumTypeWrapper
18
+ from google.protobuf.message import Message
19
+ from google.protobuf.timestamp_pb2 import Timestamp
20
+
21
+ __all__ = [
22
+ "date_to_str",
23
+ "datetime_to_timestamp",
24
+ "enum_from_proto",
25
+ "enum_to_proto",
26
+ "require",
27
+ "seconds_from_proto",
28
+ "str_list",
29
+ "timedelta_to_seconds",
30
+ "timestamp_from_proto",
31
+ ]
32
+
33
+ _E = TypeVar("_E", bound=Enum)
34
+ _CAMEL_BOUNDARY = re.compile(r"(?<!^)(?=[A-Z])")
35
+ _ISO_DATE = re.compile(r"[0-9]{4}-[0-9]{2}-[0-9]{2}")
36
+ _ONE_SECOND = timedelta(seconds=1)
37
+
38
+
39
+ def require(name: str, value: object) -> None:
40
+ """Raise ``ValueError`` when a required identifier is missing or empty."""
41
+ if value is None or value == "":
42
+ raise ValueError(f"{name} is required")
43
+
44
+
45
+ def str_list(name: str, values: Sequence[str]) -> list[str]:
46
+ """Copy ``values`` into a list, refusing a bare ``str`` (which would split into characters)."""
47
+ if isinstance(values, (str, bytes)):
48
+ raise TypeError(f"{name} must be a list of strings, not a single string")
49
+ return list(values)
50
+
51
+
52
+ def _enum_prefix(wrapper: EnumTypeWrapper) -> str:
53
+ """``TriggerDeliveryStatus`` -> ``"TRIGGER_DELIVERY_STATUS_"``."""
54
+ return _CAMEL_BOUNDARY.sub("_", wrapper.DESCRIPTOR.name).upper() + "_"
55
+
56
+
57
+ def enum_from_proto(enum_cls: type[_E], wrapper: EnumTypeWrapper, value: int) -> _E | str | None:
58
+ """Convert a proto enum number to an SDK enum member.
59
+
60
+ ``0`` (the ``*_UNSPECIFIED`` value) becomes ``None``. A value the generated code
61
+ knows is looked up by its name without the ``<ENUM_NAME>_`` prefix; when the SDK
62
+ enum has no such member, that name is returned as a plain ``str``. A number the
63
+ generated code does not know is returned as ``str(value)``. Never raises.
64
+ """
65
+ if value == 0:
66
+ return None
67
+ try:
68
+ name: str = wrapper.Name(value)
69
+ except ValueError:
70
+ return str(value)
71
+ name = name.removeprefix(_enum_prefix(wrapper))
72
+ try:
73
+ return enum_cls[name]
74
+ except KeyError:
75
+ return name
76
+
77
+
78
+ def enum_to_proto(wrapper: EnumTypeWrapper, value: Enum | str | int, field: str) -> int:
79
+ """Encode an enum member, a value name or a raw number as a proto enum number.
80
+
81
+ Names are accepted with or without the ``<ENUM_NAME>_`` prefix. A raw ``int`` is
82
+ sent as is, so values newer than this SDK can still be sent. Raises ``ValueError``
83
+ for a name the generated code does not know (it cannot be encoded).
84
+ """
85
+ if isinstance(value, bool):
86
+ raise TypeError(f"{field} must be an enum member, a name or an int, not bool")
87
+ if isinstance(value, Enum):
88
+ name = value.name
89
+ elif isinstance(value, str):
90
+ name = value
91
+ elif isinstance(value, int):
92
+ return value
93
+ else:
94
+ raise TypeError(f"{field} must be an enum member, a name or an int")
95
+ prefix = _enum_prefix(wrapper)
96
+ for candidate in (name, prefix + name):
97
+ try:
98
+ number: int = wrapper.Value(candidate)
99
+ except ValueError:
100
+ continue
101
+ return number
102
+ known = ", ".join(
103
+ v.name.removeprefix(prefix) for v in wrapper.DESCRIPTOR.values if v.number != 0
104
+ )
105
+ raise ValueError(f"unknown {field} {value!r}; expected one of: {known}, or an int")
106
+
107
+
108
+ def timestamp_from_proto(message: Message, field: str) -> datetime | None:
109
+ """Read a ``Timestamp`` field as aware UTC ``datetime``; ``None`` when it is unset."""
110
+ if not message.HasField(field):
111
+ return None
112
+ result: datetime = getattr(message, field).ToDatetime(tzinfo=timezone.utc)
113
+ return result
114
+
115
+
116
+ def datetime_to_timestamp(value: datetime, field: str) -> Timestamp:
117
+ """Encode an aware ``datetime`` as a ``Timestamp``; naive values raise ``ValueError``."""
118
+ if not isinstance(value, datetime):
119
+ raise TypeError(f"{field} must be a datetime, got {type(value).__name__}")
120
+ if value.tzinfo is None or value.utcoffset() is None:
121
+ raise ValueError(f"{field} must be timezone-aware, for example datetime.now(timezone.utc)")
122
+ timestamp = Timestamp()
123
+ timestamp.FromDatetime(value.astimezone(timezone.utc))
124
+ return timestamp
125
+
126
+
127
+ def seconds_from_proto(seconds: int) -> timedelta | None:
128
+ """A whole-seconds proto integer as ``timedelta``; ``0`` (not set) becomes ``None``."""
129
+ return timedelta(seconds=seconds) if seconds else None
130
+
131
+
132
+ def timedelta_to_seconds(value: timedelta, field: str) -> int:
133
+ """Encode a ``timedelta`` as whole seconds; a fractional second raises ``ValueError``."""
134
+ if not isinstance(value, timedelta):
135
+ raise TypeError(f"{field} must be a timedelta, got {type(value).__name__}")
136
+ if value % _ONE_SECOND:
137
+ raise ValueError(f"{field} must be a whole number of seconds, got {value!r}")
138
+ return value // _ONE_SECOND
139
+
140
+
141
+ def date_to_str(value: date | str, field: str) -> str:
142
+ """Encode a calendar date as ``YYYY-MM-DD``.
143
+
144
+ A ``date`` is used as is; an aware ``datetime`` is converted to its UTC date (a
145
+ naive one raises ``ValueError``); a ``str`` must already be a real ``YYYY-MM-DD``
146
+ date.
147
+ """
148
+ if isinstance(value, datetime):
149
+ if value.tzinfo is None or value.utcoffset() is None:
150
+ raise ValueError(f"{field} must be a date or a timezone-aware datetime")
151
+ return value.astimezone(timezone.utc).date().isoformat()
152
+ if isinstance(value, date):
153
+ return value.isoformat()
154
+ if isinstance(value, str):
155
+ if _ISO_DATE.fullmatch(value):
156
+ try:
157
+ date.fromisoformat(value)
158
+ except ValueError:
159
+ pass
160
+ else:
161
+ return value
162
+ raise ValueError(f"{field} must be a YYYY-MM-DD date, got {value!r}")
163
+ raise TypeError(f"{field} must be a date or a YYYY-MM-DD string, got {type(value).__name__}")
@@ -1,3 +1,3 @@
1
1
  # Single source of truth for the SDK version.
2
2
  # Import this in setup.py and scalekit/core.py — never hardcode the version elsewhere.
3
- __version__ = "2.21.0"
3
+ __version__ = "2.23.0"
@@ -0,0 +1,112 @@
1
+ from .actions import ActionClient
2
+ from .models.trigger_event import DeliveryScope, DetectionMode, PayloadState, TriggerEvent
3
+ from .models.triggers import (
4
+ AccountHealth,
5
+ AccountHealthAction,
6
+ AccountHealthState,
7
+ AvailableTrigger,
8
+ BatchCreateTriggerSubscriptionResult,
9
+ BatchCreateTriggerSubscriptionsResponse,
10
+ BatchDeleteTriggerSubscriptionResult,
11
+ BatchDeleteTriggerSubscriptionsResponse,
12
+ BatchLookupTriggerDeliveriesResponse,
13
+ BatchLookupTriggerDeliveryResult,
14
+ BatchResendTriggerDeliveriesResponse,
15
+ BatchResendTriggerDeliveryResult,
16
+ ConfigField,
17
+ EligibleAccount,
18
+ GenerateTriggerSigningSecretResponse,
19
+ GetTriggerActivityResponse,
20
+ GetTriggerUsageResponse,
21
+ ListAvailableTriggersResponse,
22
+ ListEligibleAccountsResponse,
23
+ ListTriggerDeliveriesByEndpointResponse,
24
+ ListTriggerDeliveryAttemptsByEndpointResponse,
25
+ ListTriggerDeliveryAttemptsByMessageResponse,
26
+ ListTriggerSubscriptionsResponse,
27
+ LookupTriggerDeliveryResponse,
28
+ RecoverTriggerDeliveriesResponse,
29
+ RequiredScope,
30
+ TriggerDelivery,
31
+ TriggerDeliveryAttempt,
32
+ TriggerDeliveryAttemptStatus,
33
+ TriggerDeliveryAttemptTriggerType,
34
+ TriggerDeliveryLookupOutcome,
35
+ TriggerDeliveryResendOutcome,
36
+ TriggerDeliveryResendTarget,
37
+ TriggerDeliveryResendTargetParam,
38
+ TriggerDeliveryStatus,
39
+ TriggerIngressEndpoint,
40
+ TriggerPlatformCredentials,
41
+ TriggerPollErrorCode,
42
+ TriggerPollState,
43
+ TriggerRefusalCode,
44
+ TriggerSubscribeOutcome,
45
+ TriggerSubscription,
46
+ TriggerSubscriptionDeleteOutcome,
47
+ TriggerSubscriptionStatus,
48
+ TriggerUsageBucket,
49
+ TriggerUsageDay,
50
+ TriggerUsageHour,
51
+ TriggerUsagePeriod,
52
+ )
53
+ from .triggers import ActionTriggers, HeadersLike, verify_trigger_event
54
+
55
+ __all__ = [
56
+ 'AccountHealth',
57
+ 'AccountHealthAction',
58
+ 'AccountHealthState',
59
+ 'ActionClient',
60
+ 'ActionTriggers',
61
+ 'AvailableTrigger',
62
+ 'BatchCreateTriggerSubscriptionResult',
63
+ 'BatchCreateTriggerSubscriptionsResponse',
64
+ 'BatchDeleteTriggerSubscriptionResult',
65
+ 'BatchDeleteTriggerSubscriptionsResponse',
66
+ 'BatchLookupTriggerDeliveriesResponse',
67
+ 'BatchLookupTriggerDeliveryResult',
68
+ 'BatchResendTriggerDeliveriesResponse',
69
+ 'BatchResendTriggerDeliveryResult',
70
+ 'ConfigField',
71
+ 'DeliveryScope',
72
+ 'DetectionMode',
73
+ 'EligibleAccount',
74
+ 'GenerateTriggerSigningSecretResponse',
75
+ 'GetTriggerActivityResponse',
76
+ 'GetTriggerUsageResponse',
77
+ 'HeadersLike',
78
+ 'ListAvailableTriggersResponse',
79
+ 'ListEligibleAccountsResponse',
80
+ 'ListTriggerDeliveriesByEndpointResponse',
81
+ 'ListTriggerDeliveryAttemptsByEndpointResponse',
82
+ 'ListTriggerDeliveryAttemptsByMessageResponse',
83
+ 'ListTriggerSubscriptionsResponse',
84
+ 'LookupTriggerDeliveryResponse',
85
+ 'PayloadState',
86
+ 'RecoverTriggerDeliveriesResponse',
87
+ 'RequiredScope',
88
+ 'TriggerDelivery',
89
+ 'TriggerDeliveryAttempt',
90
+ 'TriggerDeliveryAttemptStatus',
91
+ 'TriggerDeliveryAttemptTriggerType',
92
+ 'TriggerDeliveryLookupOutcome',
93
+ 'TriggerDeliveryResendOutcome',
94
+ 'TriggerDeliveryResendTarget',
95
+ 'TriggerDeliveryResendTargetParam',
96
+ 'TriggerDeliveryStatus',
97
+ 'TriggerEvent',
98
+ 'TriggerIngressEndpoint',
99
+ 'TriggerPlatformCredentials',
100
+ 'TriggerPollErrorCode',
101
+ 'TriggerPollState',
102
+ 'TriggerRefusalCode',
103
+ 'TriggerSubscribeOutcome',
104
+ 'TriggerSubscription',
105
+ 'TriggerSubscriptionDeleteOutcome',
106
+ 'TriggerSubscriptionStatus',
107
+ 'TriggerUsageBucket',
108
+ 'TriggerUsageDay',
109
+ 'TriggerUsageHour',
110
+ 'TriggerUsagePeriod',
111
+ 'verify_trigger_event',
112
+ ]
@@ -0,0 +1,254 @@
1
+ """Keep ``ActionClient.request`` and its credentials inside the Scalekit HTTP proxy.
2
+
3
+ ``ActionClient.request`` sends every call to ``{env_url}/proxy{path}`` with the
4
+ client's bearer token and the connection headers. This module
5
+
6
+ * verifies, before anything is sent, that the server will route the path under
7
+ ``<env base path>/proxy/`` (``ensure_under_proxy_prefix``), and
8
+ * removes those credentials from any redirect hop whose target is outside that
9
+ prefix (``ProxySession``), while following redirects exactly as ``requests``
10
+ does.
11
+
12
+ It never rewrites a URL: a request that passes is sent exactly as built.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import contextlib
18
+ import re
19
+ from collections.abc import Callable
20
+ from typing import cast
21
+ from urllib.parse import unquote
22
+
23
+ import requests
24
+ from requests.adapters import HTTPAdapter
25
+ from urllib3.exceptions import LocationParseError
26
+ from urllib3.util import parse_url
27
+
28
+ _PROXY_PREFIX = "/proxy/"
29
+
30
+ _VALID_ESCAPE_RE = re.compile(r"%[0-9A-Fa-f]{2}")
31
+
32
+ # Headers request() adds that identify the caller to Scalekit. Header names are
33
+ # case-insensitive in requests, so "Connection_name" is covered too.
34
+ _CREDENTIAL_HEADERS = ("Authorization", "connection_name", "identifier")
35
+
36
+ # Typed handles on two requests.Session methods. Some stub distributions
37
+ # (types-requests) declare them without annotations; calling them through these
38
+ # keeps strict type checking without suppressions.
39
+ _session_rebuild_auth = cast(
40
+ "Callable[[requests.Session, requests.PreparedRequest, requests.Response], None]",
41
+ requests.Session.rebuild_auth,
42
+ )
43
+ _session_should_strip_auth = cast(
44
+ "Callable[[requests.Session, str, str], bool]",
45
+ requests.Session.should_strip_auth,
46
+ )
47
+ # Only asked for request-targets (request_url); it never sends anything.
48
+ _URL_ADAPTER = HTTPAdapter()
49
+
50
+ # A proxy for every URL: request_url uses only whether one applies and its scheme.
51
+ _ANY_FORWARD_PROXY = {"all": "http://forward-proxy.invalid"}
52
+
53
+ _OUTSIDE_PROXY_MESSAGE = (
54
+ "path must resolve under the proxy prefix: start it with '/' and do not let '..' "
55
+ "segments (including percent-encoded or backslash forms) climb above it"
56
+ )
57
+
58
+
59
+ def ensure_under_proxy_prefix(env_url: str, url: str) -> None:
60
+ r"""Raise ``ValueError`` if the server would route ``url`` outside ``<base>/proxy/``.
61
+
62
+ The check starts from the path ``requests`` actually sends for ``url``
63
+ (``requests`` and ``urllib3`` may already have removed dot segments or
64
+ decoded ``%2e``). For a URL that is not ``https``, a forward proxy may be
65
+ used: ``requests`` then hands ``urllib3`` the absolute URL, and both
66
+ rebuild it (dropping an empty ``;`` parameter, removing dot segments
67
+ again), so that path is checked as well.
68
+ Each path is percent-decoded once and cleaned as Go
69
+ routers clean it (``clean_path``): runs of ``/`` collapse and dot
70
+ segments are resolved. This is done twice, as is and with ``\`` treated as
71
+ ``/``, and each result must equal ``<base>/proxy`` or start with
72
+ ``<base>/proxy/``. ``<base>`` is the path of ``env_url``, usually empty.
73
+
74
+ Args:
75
+ env_url: The environment URL the client was configured with, for
76
+ example ``"https://acme.scalekit.cloud"`` or
77
+ ``"https://host/base"``.
78
+ url: The full URL ``request()`` is about to send, built as
79
+ ``env_url.rstrip("/") + "/proxy" + path``.
80
+
81
+ Raises:
82
+ ValueError: If any server view falls outside the proxy prefix. The
83
+ message does not include the path.
84
+
85
+ Example:
86
+ >>> ensure_under_proxy_prefix("https://h", "https://h/proxy/gmail/v1/users/me")
87
+ >>> ensure_under_proxy_prefix("https://h", "https://h/proxy/x/../../outside")
88
+ Traceback (most recent call last):
89
+ ...
90
+ ValueError: path must resolve under the proxy prefix: ...
91
+ """
92
+ prepared = requests.Request(method="GET", url=url).prepare()
93
+ if not all(_path_is_under_prefix(env_url, sent) for sent in _sent_paths(prepared)):
94
+ raise ValueError(_OUTSIDE_PROXY_MESSAGE)
95
+
96
+
97
+ class ProxySession(requests.Session):
98
+ """A ``requests.Session`` that keeps proxy credentials inside the proxy prefix.
99
+
100
+ Redirects are followed exactly as ``requests`` follows them. On each hop,
101
+ ``requests`` calls ``rebuild_auth``; before deferring to it, this removes
102
+ ``Authorization``, ``connection_name`` and ``identifier`` when the hop's
103
+ target is outside ``<env base path>/proxy/``: a different origin (as
104
+ ``requests.Session.should_strip_auth`` decides) or the same origin with a
105
+ path the server would route outside the prefix (the rule
106
+ ``ensure_under_proxy_prefix`` applies). Once removed, they stay
107
+ removed for later hops. Hops that stay under the prefix are untouched.
108
+
109
+ Example:
110
+ >>> with ProxySession("https://acme.scalekit.cloud") as session:
111
+ ... response = session.request("GET", "https://acme.scalekit.cloud/proxy/x")
112
+ """
113
+
114
+ def __init__(self, env_url: str) -> None:
115
+ """Create a session for proxy calls to ``env_url``."""
116
+ super().__init__()
117
+ self._env_url = env_url
118
+ self._prefix_url = env_url.rstrip("/") + _PROXY_PREFIX
119
+
120
+ def rebuild_auth(
121
+ self, prepared_request: requests.PreparedRequest, response: requests.Response
122
+ ) -> None:
123
+ """Drop proxy credentials when a redirect leaves the proxy prefix, then defer."""
124
+ if not self._stays_in_proxy(prepared_request):
125
+ for name in _CREDENTIAL_HEADERS:
126
+ prepared_request.headers.pop(name, None)
127
+ _session_rebuild_auth(self, prepared_request, response)
128
+
129
+ def _stays_in_proxy(self, prepared_request: requests.PreparedRequest) -> bool:
130
+ url = prepared_request.url
131
+ if not url or _session_should_strip_auth(self, self._prefix_url, url):
132
+ return False
133
+ return all(
134
+ _path_is_under_prefix(self._env_url, sent) for sent in _sent_paths(prepared_request)
135
+ )
136
+
137
+
138
+ def _path_is_under_prefix(env_url: str, sent: str) -> bool:
139
+ """Return whether the server will route ``sent`` under ``<base>/proxy/``.
140
+
141
+ ``sent`` is the path as ``requests`` puts it on the wire, so any
142
+ normalisation ``requests``/``urllib3`` applied is already included. Each of
143
+ its server views (``_server_views``) must equal ``<base>/proxy`` or start
144
+ with ``<base>/proxy/``. Equality admits inputs that leave the prefix and
145
+ come back to exactly ``<base>/proxy`` (``/..%2fproxy``): they were sent the
146
+ same way before this check existed, and no proxy route matches them.
147
+ Sibling paths such as ``<base>/proxyx`` are rejected.
148
+ """
149
+ prefix = _wire_path(env_url.rstrip("/") + _PROXY_PREFIX)
150
+ for prefix_view, cleaned in zip(_server_views(prefix), _server_views(sent), strict=True):
151
+ bare = prefix_view.rstrip("/")
152
+ if cleaned != bare and not cleaned.startswith(bare + "/"):
153
+ return False
154
+ return True
155
+
156
+
157
+ def _sent_paths(prepared: requests.PreparedRequest) -> list[str]:
158
+ """Return the path of every request line ``prepared`` may be sent with.
159
+
160
+ ``requests`` decides the request-target (``HTTPAdapter.request_url``), and
161
+ this asks it for both cases: without a proxy (also a SOCKS proxy or an
162
+ ``https`` tunnel) and through a forward proxy, whether or not one is
163
+ configured. ``urllib3`` then writes the target as follows.
164
+
165
+ * A path (``/...``) is sent as is, except that ``urllib3`` may re-encode a
166
+ redirect hop's path (``_as_sent``); for a first request ``requests``
167
+ already did, and ``_as_sent`` changes nothing.
168
+ * An absolute URL (through a forward proxy, for any URL that is not
169
+ ``https``) is sent as ``urllib3.util.parse_url`` rebuilds it. That
170
+ removes dot segments again and treats ``%2F`` as part of a segment;
171
+ ``requests`` may already have dropped an empty ``;`` parameter from the
172
+ last segment, which can leave a ``..`` behind.
173
+ """
174
+ paths: list[str] = []
175
+ for proxies in (None, _ANY_FORWARD_PROXY):
176
+ target = _URL_ADAPTER.request_url(prepared, proxies)
177
+ if target.startswith("/"):
178
+ paths.append(_as_sent(target.split("?", 1)[0]))
179
+ continue
180
+ # Like urllib3's urlopen, parse any other target as an absolute URL.
181
+ # If that fails here, the send fails the same way before writing
182
+ # anything, so there is no further path to check.
183
+ with contextlib.suppress(LocationParseError):
184
+ paths.append(parse_url(target).path or "/")
185
+ return paths
186
+
187
+
188
+ def _wire_path(url: str) -> str:
189
+ """Return the path (without the query) that ``requests`` sends for ``url``.
190
+
191
+ Preparing the URL runs it through ``urllib3``'s URL parser, which already
192
+ applies the encoding ``_as_sent`` describes, so this is the wire form.
193
+ """
194
+ path_url: str = requests.Request(method="GET", url=url).prepare().path_url
195
+ return path_url.split("?", 1)[0]
196
+
197
+
198
+ def _as_sent(path: str) -> str:
199
+ """Return ``path`` as ``urllib3`` writes it in an origin-form request line.
200
+
201
+ When any ``%`` in the path does not start a valid ``%XX`` escape, ``urllib3``
202
+ encodes every ``%`` as ``%25``, so the server decodes ``%2F`` back to the
203
+ literal text ``%2F``, not to ``/``. ``urllib3`` escapes other characters as
204
+ well, but one decode restores those, so they do not change the server view.
205
+ """
206
+ if path.count("%") != len(_VALID_ESCAPE_RE.findall(path)):
207
+ return path.replace("%", "%25")
208
+ return path
209
+
210
+
211
+ def _server_views(path: str) -> tuple[str, str]:
212
+ r"""Return how a server may route ``path``: decoded once, then cleaned.
213
+
214
+ The first view is what a Go router sees (``clean_path`` of the decoded
215
+ path). The second also treats ``\`` as ``/``, as some servers and proxies
216
+ do. Both are checked: neither view alone is stricter than the other.
217
+ """
218
+ decoded = unquote(path)
219
+ return clean_path(decoded), clean_path(decoded.replace("\\", "/"))
220
+
221
+
222
+ def clean_path(path: str) -> str:
223
+ """Return ``path`` cleaned the way Go HTTP routers clean a request path.
224
+
225
+ This is Go's ``path.Clean`` on the rooted path, with a trailing slash put
226
+ back when ``path`` had one, which is how common Go routers clean the decoded
227
+ path before matching routes (and redirect to the cleaned path when it
228
+ differs). Empty and ``.`` segments are dropped, so runs of ``/`` collapse;
229
+ each ``..`` removes the segment before it, and a ``..`` at the root is
230
+ dropped.
231
+
232
+ Args:
233
+ path: A decoded URL path. A missing leading ``/`` is treated as present.
234
+
235
+ Returns:
236
+ The cleaned path, always starting with ``/``.
237
+
238
+ Example:
239
+ >>> clean_path("/proxy//../x/./y/")
240
+ '/x/y/'
241
+ """
242
+ segments: list[str] = []
243
+ for segment in path.split("/"):
244
+ if segment in ("", "."):
245
+ continue
246
+ if segment == "..":
247
+ if segments:
248
+ segments.pop()
249
+ continue
250
+ segments.append(segment)
251
+ cleaned = "/" + "/".join(segments)
252
+ if path.endswith("/") and cleaned != "/":
253
+ cleaned += "/"
254
+ return cleaned