scalekit-sdk-python 2.16.0__tar.gz → 2.18.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 (278) hide show
  1. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/PKG-INFO +91 -2
  2. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/README.md +82 -0
  3. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/_version.py +1 -1
  4. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/client.py +32 -9
  5. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/core.py +90 -9
  6. scalekit_sdk_python-2.18.0/scalekit/frameworks/django.py +369 -0
  7. scalekit_sdk_python-2.18.0/scalekit/frameworks/fastapi.py +386 -0
  8. scalekit_sdk_python-2.18.0/scalekit/frameworks/flask.py +368 -0
  9. scalekit_sdk_python-2.18.0/scalekit/middleware/csrf_state.py +57 -0
  10. scalekit_sdk_python-2.18.0/scalekit/middleware/protocol.py +56 -0
  11. scalekit_sdk_python-2.18.0/scalekit/middleware/session_crypto.py +126 -0
  12. scalekit_sdk_python-2.18.0/scalekit/middleware/session_manager.py +242 -0
  13. scalekit_sdk_python-2.18.0/scalekit/v1/webhooks/__init__.py +0 -0
  14. scalekit_sdk_python-2.18.0/scalekit/v1/workspaces/__init__.py +0 -0
  15. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/PKG-INFO +91 -2
  16. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/SOURCES.txt +17 -0
  17. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/requires.txt +10 -1
  18. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/setup.py +9 -1
  19. scalekit_sdk_python-2.18.0/tests/test_http_timeout.py +59 -0
  20. scalekit_sdk_python-2.18.0/tests/test_keepalive_channel_options.py +87 -0
  21. scalekit_sdk_python-2.18.0/tests/test_middleware_csrf_state.py +47 -0
  22. scalekit_sdk_python-2.18.0/tests/test_middleware_django.py +428 -0
  23. scalekit_sdk_python-2.18.0/tests/test_middleware_fastapi.py +434 -0
  24. scalekit_sdk_python-2.18.0/tests/test_middleware_flask.py +557 -0
  25. scalekit_sdk_python-2.18.0/tests/test_middleware_session_crypto.py +86 -0
  26. scalekit_sdk_python-2.18.0/tests/test_middleware_session_manager.py +303 -0
  27. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/LICENSE +0 -0
  28. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/buf/__init__.py +0 -0
  29. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/buf/validate/__init__.py +0 -0
  30. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/buf/validate/validate_pb2.py +0 -0
  31. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/buf/validate/validate_pb2.pyi +0 -0
  32. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/buf/validate/validate_pb2_grpc.py +0 -0
  33. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/pyproject.toml +0 -0
  34. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/__init__.py +0 -0
  35. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/__init__.py +0 -0
  36. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/actions.py +0 -0
  37. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/__init__.py +0 -0
  38. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/google_adk.py +0 -0
  39. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/langchain.py +0 -0
  40. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/types/__init__.py +0 -0
  41. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/types/google_adk_tool.py +0 -0
  42. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/frameworks/util.py +0 -0
  43. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/__init__.py +0 -0
  44. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/custom_provider.py +0 -0
  45. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_config.py +0 -0
  46. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_connection_auth_state.py +0 -0
  47. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/mcp_instance.py +0 -0
  48. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/__init__.py +0 -0
  49. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/create_connected_account_request.py +0 -0
  50. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/create_custom_provider_request.py +0 -0
  51. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/delete_custom_provider_request.py +0 -0
  52. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/list_providers_request.py +0 -0
  53. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/mcp_request.py +0 -0
  54. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/tool_request.py +0 -0
  55. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/update_connected_account_request.py +0 -0
  56. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/requests/update_custom_provider_request.py +0 -0
  57. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/__init__.py +0 -0
  58. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_connected_account_response.py +0 -0
  59. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_custom_provider_response.py +0 -0
  60. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_mcp_config_response.py +0 -0
  61. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_mcp_response.py +0 -0
  62. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/create_mcp_session_token_response.py +0 -0
  63. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_connected_account_response.py +0 -0
  64. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_custom_provider_response.py +0 -0
  65. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_mcp_config_response.py +0 -0
  66. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/delete_mcp_instance_response.py +0 -0
  67. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/ensure_mcp_instance_response.py +0 -0
  68. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/execute_tool_response.py +0 -0
  69. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_connected_account_auth_response.py +0 -0
  70. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_mcp_instance_auth_state_response.py +0 -0
  71. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_mcp_instance_response.py +0 -0
  72. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/get_mcp_response.py +0 -0
  73. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_connected_accounts_response.py +0 -0
  74. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_mcp_configs_response.py +0 -0
  75. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_mcp_connected_accounts_response.py +0 -0
  76. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_mcp_instances_response.py +0 -0
  77. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/list_providers_response.py +0 -0
  78. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/magic_link_response.py +0 -0
  79. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_connected_account_response.py +0 -0
  80. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_custom_provider_response.py +0 -0
  81. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_mcp_config_response.py +0 -0
  82. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/update_mcp_instance_response.py +0 -0
  83. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/responses/verify_connected_account_user_response.py +0 -0
  84. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/tool_input_output.py +0 -0
  85. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/models/tool_mapping.py +0 -0
  86. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/modifier.py +0 -0
  87. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/actions/types.py +0 -0
  88. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/auth.py +0 -0
  89. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/common/__init__.py +0 -0
  90. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/common/exceptions.py +0 -0
  91. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/common/scalekit.py +0 -0
  92. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/common/user.py +0 -0
  93. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/connected_accounts.py +0 -0
  94. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/connection.py +0 -0
  95. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/constants/__init__.py +0 -0
  96. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/constants/user.py +0 -0
  97. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/directory.py +0 -0
  98. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/domain.py +0 -0
  99. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/events.py +0 -0
  100. {scalekit_sdk_python-2.16.0/scalekit/utils → scalekit_sdk_python-2.18.0/scalekit/frameworks}/__init__.py +0 -0
  101. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/m2m_client.py +0 -0
  102. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/mcp.py +0 -0
  103. {scalekit_sdk_python-2.16.0/scalekit/v1 → scalekit_sdk_python-2.18.0/scalekit/middleware}/__init__.py +0 -0
  104. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/organization.py +0 -0
  105. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/passwordless.py +0 -0
  106. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/permissions.py +0 -0
  107. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/providers.py +0 -0
  108. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/role.py +0 -0
  109. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/sessions.py +0 -0
  110. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/token.py +0 -0
  111. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/tools.py +0 -0
  112. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/users.py +0 -0
  113. {scalekit_sdk_python-2.16.0/scalekit/v1/agentkit_logs → scalekit_sdk_python-2.18.0/scalekit/utils}/__init__.py +0 -0
  114. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/utils/directory.py +0 -0
  115. {scalekit_sdk_python-2.16.0/scalekit/v1/auditlogs → scalekit_sdk_python-2.18.0/scalekit/v1}/__init__.py +0 -0
  116. {scalekit_sdk_python-2.16.0/scalekit/v1/auth → scalekit_sdk_python-2.18.0/scalekit/v1/agentkit_logs}/__init__.py +0 -0
  117. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.py +0 -0
  118. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2.pyi +0 -0
  119. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_analytics_pb2_grpc.py +0 -0
  120. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2.py +0 -0
  121. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2.pyi +0 -0
  122. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/agentkit_logs/agentkit_logs_pb2_grpc.py +0 -0
  123. {scalekit_sdk_python-2.16.0/scalekit/v1/clients → scalekit_sdk_python-2.18.0/scalekit/v1/auditlogs}/__init__.py +0 -0
  124. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auditlogs/auditlogs_pb2.py +0 -0
  125. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auditlogs/auditlogs_pb2.pyi +0 -0
  126. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auditlogs/auditlogs_pb2_grpc.py +0 -0
  127. {scalekit_sdk_python-2.16.0/scalekit/v1/commons → scalekit_sdk_python-2.18.0/scalekit/v1/auth}/__init__.py +0 -0
  128. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/auth_pb2.py +0 -0
  129. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/auth_pb2.pyi +0 -0
  130. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/auth_pb2_grpc.py +0 -0
  131. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/passwordless_pb2.py +0 -0
  132. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/passwordless_pb2.pyi +0 -0
  133. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/passwordless_pb2_grpc.py +0 -0
  134. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/totp_pb2.py +0 -0
  135. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/totp_pb2.pyi +0 -0
  136. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/totp_pb2_grpc.py +0 -0
  137. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/webauthn_pb2.py +0 -0
  138. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/webauthn_pb2.pyi +0 -0
  139. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/auth/webauthn_pb2_grpc.py +0 -0
  140. {scalekit_sdk_python-2.16.0/scalekit/v1/connected_accounts → scalekit_sdk_python-2.18.0/scalekit/v1/clients}/__init__.py +0 -0
  141. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/clients/clients_pb2.py +0 -0
  142. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/clients/clients_pb2.pyi +0 -0
  143. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/clients/clients_pb2_grpc.py +0 -0
  144. {scalekit_sdk_python-2.16.0/scalekit/v1/connections → scalekit_sdk_python-2.18.0/scalekit/v1/commons}/__init__.py +0 -0
  145. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/commons/commons_pb2.py +0 -0
  146. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/commons/commons_pb2.pyi +0 -0
  147. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/commons/commons_pb2_grpc.py +0 -0
  148. {scalekit_sdk_python-2.16.0/scalekit/v1/directories → scalekit_sdk_python-2.18.0/scalekit/v1/connected_accounts}/__init__.py +0 -0
  149. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.py +0 -0
  150. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi +0 -0
  151. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py +0 -0
  152. {scalekit_sdk_python-2.16.0/scalekit/v1/domains → scalekit_sdk_python-2.18.0/scalekit/v1/connections}/__init__.py +0 -0
  153. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connections/connections_pb2.py +0 -0
  154. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connections/connections_pb2.pyi +0 -0
  155. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/connections/connections_pb2_grpc.py +0 -0
  156. {scalekit_sdk_python-2.16.0/scalekit/v1/emails → scalekit_sdk_python-2.18.0/scalekit/v1/directories}/__init__.py +0 -0
  157. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/directories/directories_pb2.py +0 -0
  158. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/directories/directories_pb2.pyi +0 -0
  159. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/directories/directories_pb2_grpc.py +0 -0
  160. {scalekit_sdk_python-2.16.0/scalekit/v1/environments → scalekit_sdk_python-2.18.0/scalekit/v1/domains}/__init__.py +0 -0
  161. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/domains/domains_pb2.py +0 -0
  162. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/domains/domains_pb2.pyi +0 -0
  163. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/domains/domains_pb2_grpc.py +0 -0
  164. {scalekit_sdk_python-2.16.0/scalekit/v1/errdetails → scalekit_sdk_python-2.18.0/scalekit/v1/emails}/__init__.py +0 -0
  165. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/emails/emails_pb2.py +0 -0
  166. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/emails/emails_pb2.pyi +0 -0
  167. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/emails/emails_pb2_grpc.py +0 -0
  168. {scalekit_sdk_python-2.16.0/scalekit/v1/events → scalekit_sdk_python-2.18.0/scalekit/v1/environments}/__init__.py +0 -0
  169. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/environments/environments_pb2.py +0 -0
  170. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/environments/environments_pb2.pyi +0 -0
  171. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/environments/environments_pb2_grpc.py +0 -0
  172. {scalekit_sdk_python-2.16.0/scalekit/v1/gateway → scalekit_sdk_python-2.18.0/scalekit/v1/errdetails}/__init__.py +0 -0
  173. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/errdetails/errdetails_pb2.py +0 -0
  174. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/errdetails/errdetails_pb2.pyi +0 -0
  175. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/errdetails/errdetails_pb2_grpc.py +0 -0
  176. {scalekit_sdk_python-2.16.0/scalekit/v1/interceptors → scalekit_sdk_python-2.18.0/scalekit/v1/events}/__init__.py +0 -0
  177. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/events/events_pb2.py +0 -0
  178. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/events/events_pb2.pyi +0 -0
  179. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/events/events_pb2_grpc.py +0 -0
  180. {scalekit_sdk_python-2.16.0/scalekit/v1/keys → scalekit_sdk_python-2.18.0/scalekit/v1/gateway}/__init__.py +0 -0
  181. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/gateway/gateway_pb2.py +0 -0
  182. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/gateway/gateway_pb2.pyi +0 -0
  183. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/gateway/gateway_pb2_grpc.py +0 -0
  184. {scalekit_sdk_python-2.16.0/scalekit/v1/mcp → scalekit_sdk_python-2.18.0/scalekit/v1/interceptors}/__init__.py +0 -0
  185. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/interceptors/interceptors_pb2.py +0 -0
  186. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/interceptors/interceptors_pb2.pyi +0 -0
  187. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/interceptors/interceptors_pb2_grpc.py +0 -0
  188. {scalekit_sdk_python-2.16.0/scalekit/v1/members → scalekit_sdk_python-2.18.0/scalekit/v1/keys}/__init__.py +0 -0
  189. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/keys/keys_pb2.py +0 -0
  190. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/keys/keys_pb2.pyi +0 -0
  191. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/keys/keys_pb2_grpc.py +0 -0
  192. {scalekit_sdk_python-2.16.0/scalekit/v1/migrations → scalekit_sdk_python-2.18.0/scalekit/v1/mcp}/__init__.py +0 -0
  193. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/mcp/mcp_pb2.py +0 -0
  194. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/mcp/mcp_pb2.pyi +0 -0
  195. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/mcp/mcp_pb2_grpc.py +0 -0
  196. {scalekit_sdk_python-2.16.0/scalekit/v1/options → scalekit_sdk_python-2.18.0/scalekit/v1/members}/__init__.py +0 -0
  197. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/members/members_pb2.py +0 -0
  198. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/members/members_pb2.pyi +0 -0
  199. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/members/members_pb2_grpc.py +0 -0
  200. {scalekit_sdk_python-2.16.0/scalekit/v1/organizations → scalekit_sdk_python-2.18.0/scalekit/v1/migrations}/__init__.py +0 -0
  201. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/migrations/migrations_pb2.py +0 -0
  202. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/migrations/migrations_pb2.pyi +0 -0
  203. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/migrations/migrations_pb2_grpc.py +0 -0
  204. {scalekit_sdk_python-2.16.0/scalekit/v1/providers → scalekit_sdk_python-2.18.0/scalekit/v1/options}/__init__.py +0 -0
  205. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/options/options_pb2.py +0 -0
  206. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/options/options_pb2.pyi +0 -0
  207. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/options/options_pb2_grpc.py +0 -0
  208. {scalekit_sdk_python-2.16.0/scalekit/v1/roles → scalekit_sdk_python-2.18.0/scalekit/v1/organizations}/__init__.py +0 -0
  209. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/organizations/organizations_pb2.py +0 -0
  210. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/organizations/organizations_pb2.pyi +0 -0
  211. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/organizations/organizations_pb2_grpc.py +0 -0
  212. {scalekit_sdk_python-2.16.0/scalekit/v1/secrets → scalekit_sdk_python-2.18.0/scalekit/v1/providers}/__init__.py +0 -0
  213. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/providers/providers_pb2.py +0 -0
  214. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/providers/providers_pb2.pyi +0 -0
  215. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/providers/providers_pb2_grpc.py +0 -0
  216. {scalekit_sdk_python-2.16.0/scalekit/v1/sessions → scalekit_sdk_python-2.18.0/scalekit/v1/roles}/__init__.py +0 -0
  217. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/roles/roles_pb2.py +0 -0
  218. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/roles/roles_pb2.pyi +0 -0
  219. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/roles/roles_pb2_grpc.py +0 -0
  220. {scalekit_sdk_python-2.16.0/scalekit/v1/tokens → scalekit_sdk_python-2.18.0/scalekit/v1/secrets}/__init__.py +0 -0
  221. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/secrets/secrets_pb2.py +0 -0
  222. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/secrets/secrets_pb2.pyi +0 -0
  223. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/secrets/secrets_pb2_grpc.py +0 -0
  224. {scalekit_sdk_python-2.16.0/scalekit/v1/tools → scalekit_sdk_python-2.18.0/scalekit/v1/sessions}/__init__.py +0 -0
  225. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/sessions/sessions_pb2.py +0 -0
  226. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/sessions/sessions_pb2.pyi +0 -0
  227. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/sessions/sessions_pb2_grpc.py +0 -0
  228. {scalekit_sdk_python-2.16.0/scalekit/v1/user_attributes → scalekit_sdk_python-2.18.0/scalekit/v1/tokens}/__init__.py +0 -0
  229. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tokens/tokens_pb2.py +0 -0
  230. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tokens/tokens_pb2.pyi +0 -0
  231. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tokens/tokens_pb2_grpc.py +0 -0
  232. {scalekit_sdk_python-2.16.0/scalekit/v1/users → scalekit_sdk_python-2.18.0/scalekit/v1/tools}/__init__.py +0 -0
  233. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tools/tools_pb2.py +0 -0
  234. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tools/tools_pb2.pyi +0 -0
  235. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/tools/tools_pb2_grpc.py +0 -0
  236. {scalekit_sdk_python-2.16.0/scalekit/v1/webhooks → scalekit_sdk_python-2.18.0/scalekit/v1/user_attributes}/__init__.py +0 -0
  237. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/user_attributes/user_attributes_pb2.py +0 -0
  238. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/user_attributes/user_attributes_pb2.pyi +0 -0
  239. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/user_attributes/user_attributes_pb2_grpc.py +0 -0
  240. {scalekit_sdk_python-2.16.0/scalekit/v1/workspaces → scalekit_sdk_python-2.18.0/scalekit/v1/users}/__init__.py +0 -0
  241. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/users/users_pb2.py +0 -0
  242. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/users/users_pb2.pyi +0 -0
  243. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/users/users_pb2_grpc.py +0 -0
  244. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/webhooks/webhooks_pb2.py +0 -0
  245. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/webhooks/webhooks_pb2.pyi +0 -0
  246. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/webhooks/webhooks_pb2_grpc.py +0 -0
  247. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/workspaces/workspaces_pb2.py +0 -0
  248. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/workspaces/workspaces_pb2.pyi +0 -0
  249. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/v1/workspaces/workspaces_pb2_grpc.py +0 -0
  250. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit/webauthn.py +0 -0
  251. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/dependency_links.txt +0 -0
  252. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/scalekit_sdk_python.egg-info/top_level.txt +0 -0
  253. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/setup.cfg +0 -0
  254. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_actions.py +0 -0
  255. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_connected_accounts.py +0 -0
  256. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_connection.py +0 -0
  257. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_directory.py +0 -0
  258. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_domain.py +0 -0
  259. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_events.py +0 -0
  260. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_login.py +0 -0
  261. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_m2m_client.py +0 -0
  262. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_mcp.py +0 -0
  263. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_org_roles.py +0 -0
  264. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_organization.py +0 -0
  265. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_organization_session_policy.py +0 -0
  266. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_organization_slug_logo.py +0 -0
  267. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_passwordless.py +0 -0
  268. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_permissions.py +0 -0
  269. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_providers.py +0 -0
  270. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_role_defaults_dependent.py +0 -0
  271. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_roles.py +0 -0
  272. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_sessions.py +0 -0
  273. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_sk819_retry_behavior.py +0 -0
  274. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_tokens.py +0 -0
  275. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_tools.py +0 -0
  276. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_user_roles_permissions.py +0 -0
  277. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.0}/tests/test_users.py +0 -0
  278. {scalekit_sdk_python-2.16.0 → scalekit_sdk_python-2.18.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.16.0
3
+ Version: 2.18.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
@@ -17,7 +17,7 @@ Requires-Dist: google>=3.0
17
17
  Requires-Dist: requests>=2.34.0
18
18
  Requires-Dist: PyJWT>=2.13.0
19
19
  Requires-Dist: cffi>=1.15.1
20
- Requires-Dist: cryptography<49,>=46.0.6
20
+ Requires-Dist: cryptography>=50.0.0
21
21
  Requires-Dist: setuptools<83.0,>=82.0.1
22
22
  Requires-Dist: grpcio-status<2.0,>=1.81.0
23
23
  Requires-Dist: protoc-gen-openapiv2>=0.0.1
@@ -27,6 +27,12 @@ Requires-Dist: python-dotenv<2.0,>=1.2.2
27
27
  Requires-Dist: Faker<41.0,>=33.0.0
28
28
  Requires-Dist: pydantic>=2.13.4
29
29
  Requires-Dist: mcp>=1.27.2
30
+ Provides-Extra: flask
31
+ Requires-Dist: flask>=2.0; extra == "flask"
32
+ Provides-Extra: fastapi
33
+ Requires-Dist: fastapi>=0.100; extra == "fastapi"
34
+ Provides-Extra: django
35
+ Requires-Dist: django>=4.2; extra == "django"
30
36
  Dynamic: author
31
37
  Dynamic: author-email
32
38
  Dynamic: classifier
@@ -35,6 +41,7 @@ Dynamic: description-content-type
35
41
  Dynamic: home-page
36
42
  Dynamic: license
37
43
  Dynamic: license-file
44
+ Dynamic: provides-extra
38
45
  Dynamic: requires-dist
39
46
  Dynamic: summary
40
47
 
@@ -178,6 +185,88 @@ Explore fully functional sample applications built with popular Python framework
178
185
  |-----------|------------|-------------|
179
186
  | **FastAPI** | [scalekit-fastapi-example](https://github.com/scalekit-developers/scalekit-fastapi-example) | Modern async Python API framework |
180
187
 
188
+ ### Full Stack Auth — encrypted-session middleware for Flask, FastAPI, and Django
189
+
190
+ The example above is for **Modular SSO**: Scalekit brokers the OAuth exchange with your customer's own IdP via a `connection_id`, and your app owns its own session however it likes.
191
+
192
+ If instead Scalekit hosts your login UI and you want it to also manage the session lifecycle for you (**Full Stack Auth**), `scalekit-sdk-python` ships optional Flask, FastAPI, and Django extras that handle the encrypted session cookie, transparent token refresh, CSRF-safe login/callback, and full logout for you — no hand-rolled cookies, no manual refresh timing.
193
+
194
+ Register these under **Dashboard → Authentication → Redirects** before testing:
195
+ - **Redirect URI** — your `redirect_uri` (the `/callback` path). Scalekit rejects the exchange if this doesn't match exactly.
196
+ - **Post Logout Redirect URI** — where users land after full logout. A relative path gets auto-absolutized against the request host, but the resulting absolute URL must still be registered.
197
+ - **Initiate Login URL** — your `/login` path. Scalekit redirects here (not `/callback`) for a bookmarked login page, an IdP portal tile, or an invite/magic link — the login view already handles this correctly, including the `idp_initiated_login` case, with no extra code required.
198
+
199
+ pip install "scalekit-sdk-python[flask]" # or "scalekit-sdk-python[fastapi]" or "scalekit-sdk-python[django]"
200
+
201
+ ```python
202
+ # Flask
203
+ import os
204
+ from flask import Flask
205
+ from scalekit.frameworks.flask import ScalekitAuth
206
+
207
+ app = Flask(__name__)
208
+ auth = ScalekitAuth(
209
+ app,
210
+ env_url=os.environ["SCALEKIT_ENV_URL"],
211
+ client_id=os.environ["SCALEKIT_CLIENT_ID"],
212
+ client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
213
+ redirect_uri="https://myapp.com/callback",
214
+ cookie_encryption_secret=os.environ["COOKIE_ENCRYPTION_SECRET"], # openssl rand -base64 32
215
+ ) # registers /login, /callback, /logout
216
+
217
+ @app.route("/account")
218
+ @auth.requires_auth
219
+ def account():
220
+ return {"email": auth.current_user["email"]}
221
+ ```
222
+
223
+ ```python
224
+ # FastAPI -- protect routes with Depends(), FastAPI's idiomatic mechanism
225
+ import os
226
+ from fastapi import Depends, FastAPI
227
+ from scalekit.frameworks.fastapi import ScalekitAuth
228
+
229
+ app = FastAPI()
230
+ auth = ScalekitAuth(
231
+ env_url=os.environ["SCALEKIT_ENV_URL"],
232
+ client_id=os.environ["SCALEKIT_CLIENT_ID"],
233
+ client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
234
+ redirect_uri="https://myapp.com/callback",
235
+ cookie_encryption_secret=os.environ["COOKIE_ENCRYPTION_SECRET"],
236
+ )
237
+ auth.install(app) # registers /login, /callback, /logout
238
+
239
+ @app.get("/account")
240
+ async def account(user: dict = Depends(auth.requires_auth)):
241
+ return {"email": user["email"]}
242
+ ```
243
+
244
+ ```python
245
+ # Django -- settings.py
246
+ import os
247
+
248
+ MIDDLEWARE = [..., "scalekit.frameworks.django.ScalekitAuthMiddleware"]
249
+ SCALEKIT_ENV_URL = os.environ["SCALEKIT_ENV_URL"]
250
+ SCALEKIT_CLIENT_ID = os.environ["SCALEKIT_CLIENT_ID"]
251
+ SCALEKIT_CLIENT_SECRET = os.environ["SCALEKIT_CLIENT_SECRET"]
252
+ SCALEKIT_REDIRECT_URI = "https://myapp.com/callback"
253
+ SCALEKIT_COOKIE_ENCRYPTION_SECRET = os.environ["COOKIE_ENCRYPTION_SECRET"]
254
+
255
+ # urls.py
256
+ from django.urls import include, path
257
+ urlpatterns = [path("", include("scalekit.frameworks.django")), ...] # /login, /callback, /logout
258
+
259
+ # views.py
260
+ from django.http import JsonResponse
261
+ from scalekit.frameworks.django import login_required
262
+
263
+ @login_required
264
+ def account(request):
265
+ return JsonResponse(request.scalekit_user)
266
+ ```
267
+
268
+ See [`examples/flask`](./examples/flask), [`examples/fastapi`](./examples/fastapi), and [`examples/django`](./examples/django) for complete, runnable versions. For a fuller production-oriented sample app, see the framework repos above.
269
+
181
270
  ## 🔗 Helpful Links
182
271
 
183
272
  ### 📖 Quickstart Guides
@@ -138,6 +138,88 @@ Explore fully functional sample applications built with popular Python framework
138
138
  |-----------|------------|-------------|
139
139
  | **FastAPI** | [scalekit-fastapi-example](https://github.com/scalekit-developers/scalekit-fastapi-example) | Modern async Python API framework |
140
140
 
141
+ ### Full Stack Auth — encrypted-session middleware for Flask, FastAPI, and Django
142
+
143
+ The example above is for **Modular SSO**: Scalekit brokers the OAuth exchange with your customer's own IdP via a `connection_id`, and your app owns its own session however it likes.
144
+
145
+ If instead Scalekit hosts your login UI and you want it to also manage the session lifecycle for you (**Full Stack Auth**), `scalekit-sdk-python` ships optional Flask, FastAPI, and Django extras that handle the encrypted session cookie, transparent token refresh, CSRF-safe login/callback, and full logout for you — no hand-rolled cookies, no manual refresh timing.
146
+
147
+ Register these under **Dashboard → Authentication → Redirects** before testing:
148
+ - **Redirect URI** — your `redirect_uri` (the `/callback` path). Scalekit rejects the exchange if this doesn't match exactly.
149
+ - **Post Logout Redirect URI** — where users land after full logout. A relative path gets auto-absolutized against the request host, but the resulting absolute URL must still be registered.
150
+ - **Initiate Login URL** — your `/login` path. Scalekit redirects here (not `/callback`) for a bookmarked login page, an IdP portal tile, or an invite/magic link — the login view already handles this correctly, including the `idp_initiated_login` case, with no extra code required.
151
+
152
+ pip install "scalekit-sdk-python[flask]" # or "scalekit-sdk-python[fastapi]" or "scalekit-sdk-python[django]"
153
+
154
+ ```python
155
+ # Flask
156
+ import os
157
+ from flask import Flask
158
+ from scalekit.frameworks.flask import ScalekitAuth
159
+
160
+ app = Flask(__name__)
161
+ auth = ScalekitAuth(
162
+ app,
163
+ env_url=os.environ["SCALEKIT_ENV_URL"],
164
+ client_id=os.environ["SCALEKIT_CLIENT_ID"],
165
+ client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
166
+ redirect_uri="https://myapp.com/callback",
167
+ cookie_encryption_secret=os.environ["COOKIE_ENCRYPTION_SECRET"], # openssl rand -base64 32
168
+ ) # registers /login, /callback, /logout
169
+
170
+ @app.route("/account")
171
+ @auth.requires_auth
172
+ def account():
173
+ return {"email": auth.current_user["email"]}
174
+ ```
175
+
176
+ ```python
177
+ # FastAPI -- protect routes with Depends(), FastAPI's idiomatic mechanism
178
+ import os
179
+ from fastapi import Depends, FastAPI
180
+ from scalekit.frameworks.fastapi import ScalekitAuth
181
+
182
+ app = FastAPI()
183
+ auth = ScalekitAuth(
184
+ env_url=os.environ["SCALEKIT_ENV_URL"],
185
+ client_id=os.environ["SCALEKIT_CLIENT_ID"],
186
+ client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
187
+ redirect_uri="https://myapp.com/callback",
188
+ cookie_encryption_secret=os.environ["COOKIE_ENCRYPTION_SECRET"],
189
+ )
190
+ auth.install(app) # registers /login, /callback, /logout
191
+
192
+ @app.get("/account")
193
+ async def account(user: dict = Depends(auth.requires_auth)):
194
+ return {"email": user["email"]}
195
+ ```
196
+
197
+ ```python
198
+ # Django -- settings.py
199
+ import os
200
+
201
+ MIDDLEWARE = [..., "scalekit.frameworks.django.ScalekitAuthMiddleware"]
202
+ SCALEKIT_ENV_URL = os.environ["SCALEKIT_ENV_URL"]
203
+ SCALEKIT_CLIENT_ID = os.environ["SCALEKIT_CLIENT_ID"]
204
+ SCALEKIT_CLIENT_SECRET = os.environ["SCALEKIT_CLIENT_SECRET"]
205
+ SCALEKIT_REDIRECT_URI = "https://myapp.com/callback"
206
+ SCALEKIT_COOKIE_ENCRYPTION_SECRET = os.environ["COOKIE_ENCRYPTION_SECRET"]
207
+
208
+ # urls.py
209
+ from django.urls import include, path
210
+ urlpatterns = [path("", include("scalekit.frameworks.django")), ...] # /login, /callback, /logout
211
+
212
+ # views.py
213
+ from django.http import JsonResponse
214
+ from scalekit.frameworks.django import login_required
215
+
216
+ @login_required
217
+ def account(request):
218
+ return JsonResponse(request.scalekit_user)
219
+ ```
220
+
221
+ See [`examples/flask`](./examples/flask), [`examples/fastapi`](./examples/fastapi), and [`examples/django`](./examples/django) for complete, runnable versions. For a fuller production-oriented sample app, see the framework repos above.
222
+
141
223
  ## 🔗 Helpful Links
142
224
 
143
225
  ### 📖 Quickstart Guides
@@ -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.16.0"
3
+ __version__ = "2.18.0"
@@ -9,7 +9,7 @@ import hmac
9
9
  import hashlib
10
10
  import base64
11
11
  from datetime import datetime, timedelta, timezone
12
- from scalekit.core import CoreClient
12
+ from scalekit.core import CoreClient, DEFAULT_KEEPALIVE_TIME_MS, DEFAULT_KEEPALIVE_TIMEOUT_MS
13
13
  from scalekit.domain import DomainClient
14
14
  from scalekit.connection import ConnectionClient
15
15
  from scalekit.m2m_client import M2MClient
@@ -50,23 +50,46 @@ webhook_signature_version = "v1"
50
50
  class ScalekitClient:
51
51
  """ Class definition for scalekit client """
52
52
 
53
- def __init__(self, env_url: str, client_id: str, client_secret: str):
53
+ def __init__(
54
+ self,
55
+ env_url: str,
56
+ client_id: str,
57
+ client_secret: str,
58
+ keepalive_time_ms: int = DEFAULT_KEEPALIVE_TIME_MS,
59
+ keepalive_timeout_ms: int = DEFAULT_KEEPALIVE_TIMEOUT_MS,
60
+ ):
54
61
  """
55
62
  Initializer for Scalekit base class
56
63
 
57
- :param env_url : Environment URL
58
- :type : ``` str ```
59
- :param client_id : Client ID
60
- :type : ``` str ```
61
- :param client_secret : Client Secret
62
- :type : ``` str ```
64
+ :param env_url : Environment URL
65
+ :type : ``` str ```
66
+ :param client_id : Client ID
67
+ :type : ``` str ```
68
+ :param client_secret : Client Secret
69
+ :type : ``` str ```
70
+ :param keepalive_time_ms : How often, in milliseconds, an idle gRPC
71
+ connection is verified before reuse.
72
+ Defaults to 60000; most callers never
73
+ need to set this. Set to 0 to disable
74
+ keepalive entirely.
75
+ :type : ``` int ```
76
+ :param keepalive_timeout_ms : How long, in milliseconds, to wait for a
77
+ keepalive response before treating an
78
+ idle connection as dead. Defaults to
79
+ 10000.
80
+ :type : ``` int ```
63
81
 
64
82
  :returns:
65
83
  None
66
84
  """
67
85
  try:
68
86
  self.core_client = CoreClient(
69
- env_url=env_url, client_id=client_id, client_secret=client_secret)
87
+ env_url=env_url,
88
+ client_id=client_id,
89
+ client_secret=client_secret,
90
+ keepalive_time_ms=keepalive_time_ms,
91
+ keepalive_timeout_ms=keepalive_timeout_ms,
92
+ )
70
93
  self.domain = DomainClient(self.core_client)
71
94
  self.connection = ConnectionClient(self.core_client)
72
95
  self.organization = OrganizationClient(self.core_client)
@@ -19,6 +19,33 @@ TMetadata = TypeVar("TMetadata")
19
19
  TOKEN_ENDPOINT = "/oauth/token"
20
20
  JWKS_ENDPOINT = "/keys"
21
21
 
22
+ # Must clear the backend's EnforcementPolicy.MinTime (30s, scalekit's
23
+ # cmd/grpc.go) with real margin, not just match it: grpc-core pings on this
24
+ # exact interval for as long as the channel is open (keepalive_permit_without_calls
25
+ # below), so a value equal to MinTime leaves zero room for jitter between the
26
+ # client's timer and the server's strike window — one early ping is a strike,
27
+ # three and the server GOAWAYs the connection, recreating the bug this fixes.
28
+ # 60s matches the Java SDK's default for the same reason.
29
+ DEFAULT_KEEPALIVE_TIME_MS = 60_000
30
+ DEFAULT_KEEPALIVE_TIMEOUT_MS = 10_000
31
+
32
+ # The floor tracks DEFAULT_KEEPALIVE_TIME_MS for the reason spelled out above:
33
+ # the backend's EnforcementPolicy.MinTime is 30s, and a value at exactly 30s has
34
+ # zero jitter headroom — grpc's ping timer drifts slightly early, so an early
35
+ # ping counts as a strike and enough strikes make the server GOAWAY. 60s gives
36
+ # 2x margin over the 30s MinTime. Since there is no legitimate reason to go below
37
+ # the default, the only sensible choices are 0 (disabled) or >= 60s. (gRPC also
38
+ # silently clamps sub-10s values up to 10s per grpc/proposal A8, so a small value
39
+ # never even reaches the wire as requested.) Reject 1..59999.
40
+ MIN_KEEPALIVE_TIME_MS = 60_000
41
+
42
+ # requests defaults to no timeout, so a black-holed connection blocks the
43
+ # calling thread until the OS abandons the socket. Bound the connect and read
44
+ # phases separately with a (connect, read) tuple.
45
+ DEFAULT_HTTP_CONNECT_TIMEOUT_S = 10
46
+ DEFAULT_HTTP_READ_TIMEOUT_S = 30
47
+ DEFAULT_HTTP_TIMEOUT = (DEFAULT_HTTP_CONNECT_TIMEOUT_S, DEFAULT_HTTP_READ_TIMEOUT_S)
48
+
22
49
 
23
50
  class WithCall(Protocol):
24
51
  def __call__(self, request: TRequest, metadata: TMetadata) -> TResponse: ...
@@ -32,16 +59,36 @@ class CoreClient:
32
59
  api_version = "20260727"
33
60
  user_agent = f"{sdk_version} Python/{platform.python_version()} ({platform.system()}; {platform.architecture()}"
34
61
 
35
- def __init__(self, env_url, client_id, client_secret):
62
+ def __init__(
63
+ self,
64
+ env_url,
65
+ client_id,
66
+ client_secret,
67
+ keepalive_time_ms: int = DEFAULT_KEEPALIVE_TIME_MS,
68
+ keepalive_timeout_ms: int = DEFAULT_KEEPALIVE_TIMEOUT_MS,
69
+ ):
36
70
  """
37
71
  Initializer for Core client
38
72
 
39
- :param env_url : Environment URL
40
- :type : ``` str ```
41
- :param client_id : Client ID
42
- :type : ``` str ```
43
- :param client_secret : Client Secret
44
- :type : ``` str ```
73
+ :param env_url : Environment URL
74
+ :type : ``` str ```
75
+ :param client_id : Client ID
76
+ :type : ``` str ```
77
+ :param client_secret : Client Secret
78
+ :type : ``` str ```
79
+ :param keepalive_time_ms : How often, in milliseconds, an idle gRPC
80
+ connection is verified before reuse.
81
+ Must stay above the backend's keepalive
82
+ MinTime (30s) with real margin, or the
83
+ server treats this ping as abuse. Defaults
84
+ to 60000. Set to 0 to disable keepalive
85
+ entirely.
86
+ :type : ``` int ```
87
+ :param keepalive_timeout_ms : How long, in milliseconds, to wait for a
88
+ keepalive response before treating an
89
+ idle connection as dead. Defaults to
90
+ 10000.
91
+ :type : ``` int ```
45
92
  :returns
46
93
  None
47
94
  """
@@ -50,6 +97,20 @@ class CoreClient:
50
97
  self.env_url = env_url
51
98
  self.client_id = client_id
52
99
  self.client_secret = client_secret
100
+ # 0 means "disabled" and is allowed through deliberately; only 1..59999
101
+ # is rejected. A value below the 60s default leaves too little margin
102
+ # over the Scalekit server's 30s MinTime — an early ping gets struck as
103
+ # abusive and the server GOAWAYs — and gRPC silently raises sub-10s
104
+ # values to 10s, so a small value is never what the caller asked for.
105
+ if keepalive_time_ms and keepalive_time_ms < MIN_KEEPALIVE_TIME_MS:
106
+ raise ValueError(
107
+ f"keepalive_time_ms must be 0 (disabled) or >= {MIN_KEEPALIVE_TIME_MS}; "
108
+ f"got {keepalive_time_ms}. A value below the default leaves too little "
109
+ "margin over the Scalekit server's 30s MinTime (early pings are struck "
110
+ "as abusive), and gRPC silently raises sub-10s values to 10s."
111
+ )
112
+ self.keepalive_time_ms = keepalive_time_ms
113
+ self.keepalive_timeout_ms = keepalive_timeout_ms
53
114
  self.keys = {}
54
115
  self.access_token = None
55
116
  self.grpc_secure_channel = None
@@ -70,7 +131,24 @@ class CoreClient:
70
131
  channel_credentials,
71
132
  call_credentials,
72
133
  )
73
- self.grpc_secure_channel = grpc.secure_channel(self.host, composite_credentials)
134
+ # keepalive_time_ms == 0 disables keepalive entirely: no options are
135
+ # passed, so grpc-core falls back to its own defaults (no idle pings).
136
+ channel_options = []
137
+ if self.keepalive_time_ms:
138
+ # keepalive_permit_without_calls=1 so an idle channel is still
139
+ # periodically verified: without it, grpc-core only sends HTTP/2
140
+ # keepalive PINGs while there are active calls, so a connection
141
+ # silently dropped by a network intermediary while idle isn't
142
+ # detected until the next real call is written to it.
143
+ channel_options = [
144
+ ('grpc.keepalive_time_ms', self.keepalive_time_ms),
145
+ ('grpc.keepalive_timeout_ms', self.keepalive_timeout_ms),
146
+ ('grpc.keepalive_permit_without_calls', 1),
147
+ ('grpc.http2.max_pings_without_data', 0),
148
+ ]
149
+ self.grpc_secure_channel = grpc.secure_channel(
150
+ self.host, composite_credentials, options=channel_options
151
+ )
74
152
 
75
153
  def __authenticate_client(self):
76
154
  """
@@ -104,6 +182,7 @@ class CoreClient:
104
182
  headers=self.get_headers(headers=headers),
105
183
  data=data,
106
184
  verify=True,
185
+ timeout=DEFAULT_HTTP_TIMEOUT,
107
186
  )
108
187
  if response.status_code != 200:
109
188
  raise ScalekitServerException.promote(response)
@@ -114,7 +193,9 @@ class CoreClient:
114
193
  if self.keys and len(self.keys) > 0:
115
194
  return
116
195
  response = requests.get(
117
- self.env_url + JWKS_ENDPOINT, headers=self.get_headers()
196
+ self.env_url + JWKS_ENDPOINT,
197
+ headers=self.get_headers(),
198
+ timeout=DEFAULT_HTTP_TIMEOUT,
118
199
  )
119
200
  response = json.loads(response.content)
120
201
  keys = response["keys"]