tempest-fastapi-sdk 0.44.0__tar.gz → 0.45.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 (383) hide show
  1. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/CHANGELOG.md +22 -0
  2. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/PKG-INFO +2 -2
  3. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/README.md +1 -1
  4. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/index.en.md +1 -0
  5. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/index.md +1 -0
  6. tempest_fastapi_sdk-0.45.0/docs/recipes/multi-tenant.en.md +120 -0
  7. tempest_fastapi_sdk-0.45.0/docs/recipes/multi-tenant.md +120 -0
  8. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/reference.md +1 -0
  9. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/mkdocs.yml +2 -0
  10. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/pyproject.toml +1 -1
  11. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/__init__.py +3 -1
  12. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/__init__.py +4 -0
  13. tempest_fastapi_sdk-0.45.0/tempest_fastapi_sdk/db/tenant.py +348 -0
  14. tempest_fastapi_sdk-0.45.0/tests/db/test_tenant.py +170 -0
  15. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/uv.lock +1 -1
  16. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/.github/workflows/ci.yml +0 -0
  17. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/.github/workflows/docs.yml +0 -0
  18. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/.github/workflows/release-pypi.yml +0 -0
  19. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/.gitignore +0 -0
  20. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/.python-version +0 -0
  21. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/CLAUDE.md +0 -0
  22. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/Makefile +0 -0
  23. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/architecture.en.md +0 -0
  24. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/architecture.md +0 -0
  25. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/changelog.en.md +0 -0
  26. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/changelog.md +0 -0
  27. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/contributing.en.md +0 -0
  28. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/contributing.md +0 -0
  29. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/index.en.md +0 -0
  30. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/index.md +0 -0
  31. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/installation.en.md +0 -0
  32. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/installation.md +0 -0
  33. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/index.en.md +0 -0
  34. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/index.md +0 -0
  35. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/api.en.md +0 -0
  36. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/api.md +0 -0
  37. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/business-rules.en.md +0 -0
  38. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/business-rules.md +0 -0
  39. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/domain.en.md +0 -0
  40. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/domain.md +0 -0
  41. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/flows.en.md +0 -0
  42. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/flows.md +0 -0
  43. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/index.en.md +0 -0
  44. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/learning/marketplace/index.md +0 -0
  45. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/migration.en.md +0 -0
  46. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/migration.md +0 -0
  47. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/admin.en.md +0 -0
  48. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/admin.md +0 -0
  49. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/auth-flow.en.md +0 -0
  50. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/auth-flow.md +0 -0
  51. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/br-helpers.en.md +0 -0
  52. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/br-helpers.md +0 -0
  53. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/cache.en.md +0 -0
  54. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/cache.md +0 -0
  55. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/cli.en.md +0 -0
  56. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/cli.md +0 -0
  57. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/database.en.md +0 -0
  58. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/database.md +0 -0
  59. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/downloads.en.md +0 -0
  60. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/downloads.md +0 -0
  61. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/email.en.md +0 -0
  62. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/email.md +0 -0
  63. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/http-client.en.md +0 -0
  64. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/http-client.md +0 -0
  65. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/http.en.md +0 -0
  66. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/http.md +0 -0
  67. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/idempotency.en.md +0 -0
  68. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/idempotency.md +0 -0
  69. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/logging.en.md +0 -0
  70. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/logging.md +0 -0
  71. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/metrics.en.md +0 -0
  72. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/metrics.md +0 -0
  73. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/mfa.en.md +0 -0
  74. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/mfa.md +0 -0
  75. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/observability.en.md +0 -0
  76. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/observability.md +0 -0
  77. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/outbox.en.md +0 -0
  78. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/outbox.md +0 -0
  79. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/queue-tasks.en.md +0 -0
  80. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/queue-tasks.md +0 -0
  81. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/realtime.en.md +0 -0
  82. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/realtime.md +0 -0
  83. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/security.en.md +0 -0
  84. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/security.md +0 -0
  85. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/sessions.en.md +0 -0
  86. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/sessions.md +0 -0
  87. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/storage.en.md +0 -0
  88. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/storage.md +0 -0
  89. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/testing.en.md +0 -0
  90. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/testing.md +0 -0
  91. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/uploads.en.md +0 -0
  92. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/uploads.md +0 -0
  93. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/utilities.en.md +0 -0
  94. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/utilities.md +0 -0
  95. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/webpush.en.md +0 -0
  96. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/webpush.md +0 -0
  97. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/websocket.en.md +0 -0
  98. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/recipes/websocket.md +0 -0
  99. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/reference.en.md +0 -0
  100. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/roadmap.en.md +0 -0
  101. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/roadmap.md +0 -0
  102. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/tutorial.en.md +0 -0
  103. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/docs/tutorial.md +0 -0
  104. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/scripts/extract_recipe.py +0 -0
  105. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
  106. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
  107. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/config.py +0 -0
  108. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
  109. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/router.py +0 -0
  110. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/session.py +0 -0
  111. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/site.py +0 -0
  112. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
  113. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
  114. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
  115. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
  116. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
  117. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
  118. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
  119. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
  120. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
  121. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
  122. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
  123. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
  124. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/dependencies/auth.py +0 -0
  125. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
  126. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
  127. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
  128. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
  129. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
  130. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
  131. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
  132. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
  133. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
  134. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
  135. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
  136. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
  137. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
  138. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
  139. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/server.py +0 -0
  140. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/static.py +0 -0
  141. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
  142. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
  143. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/__init__.py +0 -0
  144. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
  145. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/router.py +0 -0
  146. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
  147. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/service.py +0 -0
  148. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/templates/activation.html +0 -0
  149. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/templates/activation_error.html +0 -0
  150. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/templates/activation_success.html +0 -0
  151. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/templates/password_reset.html +0 -0
  152. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/templates/password_reset_error.html +0 -0
  153. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/templates/password_reset_form.html +0 -0
  154. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/auth/templates/password_reset_success.html +0 -0
  155. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
  156. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
  157. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
  158. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
  159. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
  160. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
  161. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
  162. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
  163. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
  164. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
  165. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
  166. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
  167. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
  168. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
  169. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
  170. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
  171. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
  172. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
  173. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
  174. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
  175. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
  176. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
  177. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
  178. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
  179. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
  180. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
  181. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
  182. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
  183. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
  184. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
  185. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/db.py +0 -0
  186. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
  187. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
  188. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
  189. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/main.py +0 -0
  190. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/new.py +0 -0
  191. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
  192. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/cli/user.py +0 -0
  193. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
  194. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
  195. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
  196. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/core/context.py +0 -0
  197. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/core/enums.py +0 -0
  198. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/core/logging.py +0 -0
  199. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
  200. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
  201. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
  202. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/connection.py +0 -0
  203. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
  204. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
  205. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/model.py +0 -0
  206. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
  207. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/repository.py +0 -0
  208. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
  209. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
  210. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
  211. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
  212. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
  213. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
  214. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
  215. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
  216. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
  217. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
  218. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
  219. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
  220. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
  221. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
  222. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/py.typed +0 -0
  223. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
  224. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
  225. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
  226. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
  227. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
  228. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
  229. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
  230. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
  231. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
  232. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/services/base.py +0 -0
  233. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
  234. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
  235. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
  236. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
  237. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
  238. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
  239. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
  240. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
  241. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/settings/base.py +0 -0
  242. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/settings/mixins.py +0 -0
  243. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sse/__init__.py +0 -0
  244. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/sse/event_stream.py +0 -0
  245. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
  246. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
  247. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
  248. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
  249. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
  250. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
  251. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/testing/database.py +0 -0
  252. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
  253. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
  254. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
  255. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
  256. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/download.py +0 -0
  257. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/email.py +0 -0
  258. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
  259. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
  260. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/log.py +0 -0
  261. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
  262. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
  263. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/password.py +0 -0
  264. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
  265. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
  266. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
  267. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
  268. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
  269. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
  270. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
  271. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
  272. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
  273. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
  274. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
  275. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
  276. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/__init__.py +0 -0
  277. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/__init__.py +0 -0
  278. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/test_auth.py +0 -0
  279. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/test_forms.py +0 -0
  280. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/test_logs_nav.py +0 -0
  281. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/test_mfa.py +0 -0
  282. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/test_router.py +0 -0
  283. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/test_site.py +0 -0
  284. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/admin/test_user_model.py +0 -0
  285. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/__init__.py +0 -0
  286. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_body_size.py +0 -0
  287. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_cookies.py +0 -0
  288. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_cors.py +0 -0
  289. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_csrf.py +0 -0
  290. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_dependencies_auth.py +0 -0
  291. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_handlers.py +0 -0
  292. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_health_router.py +0 -0
  293. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_idempotency.py +0 -0
  294. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_jwt_dependency.py +0 -0
  295. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_logs_router.py +0 -0
  296. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_oauth.py +0 -0
  297. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_prometheus.py +0 -0
  298. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_rate_limit.py +0 -0
  299. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_request_id_middleware.py +0 -0
  300. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_role_dependency.py +0 -0
  301. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_server.py +0 -0
  302. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_static.py +0 -0
  303. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_tool_spec.py +0 -0
  304. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_tracing.py +0 -0
  305. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_webhooks.py +0 -0
  306. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/api/test_webhooks_rsa.py +0 -0
  307. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/auth/__init__.py +0 -0
  308. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/auth/test_mfa.py +0 -0
  309. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/auth/test_service.py +0 -0
  310. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cache/__init__.py +0 -0
  311. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cache/test_decorator.py +0 -0
  312. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cache/test_redis_manager.py +0 -0
  313. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cli/__init__.py +0 -0
  314. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cli/test_db.py +0 -0
  315. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cli/test_docker_compose.py +0 -0
  316. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cli/test_generate.py +0 -0
  317. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cli/test_main.py +0 -0
  318. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/cli/test_user.py +0 -0
  319. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/conftest.py +0 -0
  320. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/controllers/__init__.py +0 -0
  321. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/controllers/test_base.py +0 -0
  322. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/core/__init__.py +0 -0
  323. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/core/test_context.py +0 -0
  324. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/core/test_enums.py +0 -0
  325. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/core/test_logging.py +0 -0
  326. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/__init__.py +0 -0
  327. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_alembic_hooks.py +0 -0
  328. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_bulk_ops.py +0 -0
  329. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_connection.py +0 -0
  330. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_migrations.py +0 -0
  331. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_mixins.py +0 -0
  332. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_model.py +0 -0
  333. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_outbox.py +0 -0
  334. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_repository.py +0 -0
  335. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/db/test_slow_query.py +0 -0
  336. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/exceptions/__init__.py +0 -0
  337. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/exceptions/test_exceptions.py +0 -0
  338. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/queue/__init__.py +0 -0
  339. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/queue/test_manager.py +0 -0
  340. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/schemas/__init__.py +0 -0
  341. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/schemas/test_base.py +0 -0
  342. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/schemas/test_cursor_pagination.py +0 -0
  343. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/schemas/test_link_headers.py +0 -0
  344. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/schemas/test_pagination.py +0 -0
  345. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/schemas/test_response.py +0 -0
  346. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/services/__init__.py +0 -0
  347. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/services/test_base.py +0 -0
  348. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/sessions/__init__.py +0 -0
  349. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/sessions/test_sessions.py +0 -0
  350. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/settings/__init__.py +0 -0
  351. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/settings/test_base.py +0 -0
  352. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/settings/test_mixins.py +0 -0
  353. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/sse/__init__.py +0 -0
  354. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/sse/test_event_stream.py +0 -0
  355. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/storage/__init__.py +0 -0
  356. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/storage/test_minio_client.py +0 -0
  357. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/tasks/__init__.py +0 -0
  358. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/tasks/test_manager.py +0 -0
  359. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/tasks/test_scheduler.py +0 -0
  360. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/testing/__init__.py +0 -0
  361. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/testing/test_database.py +0 -0
  362. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/__init__.py +0 -0
  363. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_client_ip.py +0 -0
  364. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_datetime.py +0 -0
  365. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_dict.py +0 -0
  366. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_download.py +0 -0
  367. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_email.py +0 -0
  368. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_http_client.py +0 -0
  369. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_jwt.py +0 -0
  370. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_lazy_extras.py +0 -0
  371. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_log.py +0 -0
  372. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_metrics.py +0 -0
  373. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_opaque_token.py +0 -0
  374. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_password.py +0 -0
  375. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_regex.py +0 -0
  376. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_storage_backends.py +0 -0
  377. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_throttle.py +0 -0
  378. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/utils/test_upload.py +0 -0
  379. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/webpush/__init__.py +0 -0
  380. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/webpush/test_dispatcher.py +0 -0
  381. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/webpush/test_schemas.py +0 -0
  382. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/websockets/__init__.py +0 -0
  383. {tempest_fastapi_sdk-0.44.0 → tempest_fastapi_sdk-0.45.0}/tests/websockets/test_hub_and_router.py +0 -0
@@ -5,6 +5,28 @@ All notable changes to **tempest-fastapi-sdk** are listed below.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.45.0] — 2026-06-11
9
+
10
+ ### Added
11
+
12
+ - **`TenantScopedRepository[ModelType]`** — a `BaseRepository` locked
13
+ to a single tenant for shared-schema multi-tenancy. Bind a
14
+ `tenant_id` (and optional `tenant_field`, default `"tenant_id"`) at
15
+ construction; it injects `WHERE tenant_id = ?` into **every** read
16
+ (`get`/`get_or_none`/`get_by_id`/`exists`/`first`/`list`/`count`/
17
+ `paginate`/`cursor_paginate`/`delete_many`) and stamps the tenant id
18
+ onto **every** write (`add`/`add_all`). `delete` / `delete_batch` add
19
+ the tenant predicate to the `DELETE` so a guessed id from another
20
+ tenant matches nothing — cross-tenant access (even probing existence
21
+ by id) is impossible through the repository. The constructor raises
22
+ `AttributeError` at boot if the model lacks the tenant column.
23
+ `tenant_column` property exposes the mapped column for custom queries.
24
+
25
+ ### Docs
26
+
27
+ - New bilingual recipe **Multi-tenant**, added to the nav (under
28
+ Database), the recipes index, and the API reference.
29
+
8
30
  ## [0.44.0] — 2026-06-11
9
31
 
10
32
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tempest-fastapi-sdk
3
- Version: 0.44.0
3
+ Version: 0.45.0
4
4
  Summary: Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects.
5
5
  Project-URL: Homepage, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
6
6
  Project-URL: Repository, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
@@ -238,7 +238,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
238
238
  | Module | Exports |
239
239
  | --- | --- |
240
240
  | `tempest_fastapi_sdk.schemas` | `BaseSchema`, `BaseResponseSchema`, `BasePaginationFilterSchema`, `BasePaginationSchema[T]`, `CursorPaginationFilterSchema`, `CursorPaginationSchema`, `LogEntrySchema`, `encode_cursor`, `decode_cursor`, `build_pagination_link_header` |
241
- | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox` |
241
+ | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `TenantScopedRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox` |
242
242
  | `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException` |
243
243
  | `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
244
244
  | `tempest_fastapi_sdk.api` | `register_exception_handlers`, `app_exception_handler`, `apply_cors`, `make_health_router`, `make_logs_router`, `make_prometheus_router`, `make_prometheus_registry`, `PrometheusMiddleware`, `LogSource`, `make_tool_spec_router`, `make_token_dependency`, `make_bearer_token_dependency`, `make_jwt_user_dependency`, `make_role_dependency`, `make_permission_dependency`, `require_x_token`, `run_server`, `RequestIDMiddleware`, `RateLimitMiddleware`, `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
@@ -136,7 +136,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
136
136
  | Module | Exports |
137
137
  | --- | --- |
138
138
  | `tempest_fastapi_sdk.schemas` | `BaseSchema`, `BaseResponseSchema`, `BasePaginationFilterSchema`, `BasePaginationSchema[T]`, `CursorPaginationFilterSchema`, `CursorPaginationSchema`, `LogEntrySchema`, `encode_cursor`, `decode_cursor`, `build_pagination_link_header` |
139
- | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox` |
139
+ | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `TenantScopedRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox` |
140
140
  | `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException` |
141
141
  | `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
142
142
  | `tempest_fastapi_sdk.api` | `register_exception_handlers`, `app_exception_handler`, `apply_cors`, `make_health_router`, `make_logs_router`, `make_prometheus_router`, `make_prometheus_registry`, `PrometheusMiddleware`, `LogSource`, `make_tool_spec_router`, `make_token_dependency`, `make_bearer_token_dependency`, `make_jwt_user_dependency`, `make_role_dependency`, `make_permission_dependency`, `require_x_token`, `run_server`, `RequestIDMiddleware`, `RateLimitMiddleware`, `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
@@ -10,6 +10,7 @@ Bite-sized "I want to wire X" walkthroughs. Each page starts with **what problem
10
10
  | Theme | Covers |
11
11
  | --- | --- |
12
12
  | **[Database »](database.md)** | `BaseRepository`, `BaseModel`, `AuditMixin` / `SoftDeleteMixin`, cursor pagination, Alembic helper |
13
+ | **[Multi-tenant »](multi-tenant.md)** | `TenantScopedRepository` — `tenant_id` isolation on every query |
13
14
  | **[HTTP layer »](http.md)** | `apply_cors`, `RequestIDMiddleware`, `RateLimitMiddleware`, `make_health_router`, JWT / role / permission dependencies, webhook signature verifier, pagination Link headers, tool-spec router |
14
15
  | **[HTTP client (outbound) »](http-client.md)** | `HTTPClient` — typed httpx with retry/backoff, circuit-breaker, X-Request-ID; `RetryPolicy`, `CircuitOpenError` |
15
16
  | **[Cache »](cache.md)** | `AsyncRedisManager`, `@cached` decorator |
@@ -10,6 +10,7 @@ Passo a passo curtos no estilo "quero conectar X". Cada página começa com **qu
10
10
  | Tema | Cobre |
11
11
  | --- | --- |
12
12
  | **[Banco de dados »](database.md)** | `BaseRepository`, `BaseModel`, `AuditMixin` / `SoftDeleteMixin`, paginação por cursor, helper de Alembic |
13
+ | **[Multi-tenant »](multi-tenant.md)** | `TenantScopedRepository` — isolamento por `tenant_id` em toda query |
13
14
  | **[Camada HTTP »](http.md)** | `apply_cors`, `RequestIDMiddleware`, `RateLimitMiddleware`, `make_health_router`, dependências de JWT / role / permissão, verificador de assinatura de webhook, headers Link de paginação, router de tool-spec |
14
15
  | **[HTTP client (saída) »](http-client.md)** | `HTTPClient` — httpx tipado com retry/backoff, circuit-breaker, X-Request-ID; `RetryPolicy`, `CircuitOpenError` |
15
16
  | **[Cache »](cache.md)** | `AsyncRedisManager`, decorator `@cached` |
@@ -0,0 +1,120 @@
1
+ # Multi-tenant (TenantScopedRepository)
2
+
3
+ In a **shared-schema** multi-tenant database, every tenant's rows live in
4
+ the same table, told apart by a `tenant_id` column. The danger is obvious:
5
+ forget **one** `WHERE tenant_id = ?` and tenant A reads (or deletes)
6
+ tenant B's data. `TenantScopedRepository` takes that risk off the table —
7
+ you bind the `tenant_id` at construction and it injects the filter into
8
+ **every** read and stamps it onto **every** write. Call sites can't get it
9
+ wrong.
10
+
11
+ !!! info "Where this fits"
12
+ It's a `BaseRepository` that behaves identically — same API
13
+ ([Database](database.md)). The difference is invisible to the caller:
14
+ tenant scoping is automatic.
15
+
16
+ ## 1. The model needs a tenant column
17
+
18
+ ```python
19
+ from uuid import UUID
20
+
21
+ from sqlalchemy import String, Uuid
22
+ from sqlalchemy.orm import Mapped, mapped_column
23
+
24
+ from tempest_fastapi_sdk import BaseModel
25
+
26
+
27
+ class OrderModel(BaseModel):
28
+ """Order — isolated per tenant."""
29
+
30
+ __tablename__ = "order"
31
+
32
+ tenant_id: Mapped[UUID] = mapped_column(Uuid(), nullable=False, index=True)
33
+ total: Mapped[int] = mapped_column(nullable=False)
34
+ ```
35
+
36
+ ## 2. Build the repository bound to the tenant
37
+
38
+ The `tenant_id` usually comes from the request's JWT / session / header:
39
+
40
+ ```python
41
+ from uuid import UUID
42
+
43
+ from sqlalchemy.ext.asyncio import AsyncSession
44
+
45
+ from tempest_fastapi_sdk import TenantScopedRepository
46
+
47
+ from src.db.models import OrderModel
48
+
49
+
50
+ def get_order_repo(
51
+ session: AsyncSession, tenant_id: UUID
52
+ ) -> TenantScopedRepository[OrderModel]:
53
+ """Order repository locked to the request's tenant."""
54
+ return TenantScopedRepository(session, model=OrderModel, tenant_id=tenant_id)
55
+ ```
56
+
57
+ If the model has no `tenant_id` column, the constructor raises
58
+ `AttributeError` immediately — you catch the mistake at boot, not in
59
+ production. Different column name? Pass `tenant_field="org_id"`.
60
+
61
+ ## 3. Use it like any repository
62
+
63
+ Every read comes filtered; every write comes stamped:
64
+
65
+ ```python
66
+ from uuid import UUID
67
+
68
+ from tempest_fastapi_sdk import TenantScopedRepository
69
+
70
+ from src.db.models import OrderModel
71
+
72
+
73
+ async def list_orders(repo: TenantScopedRepository[OrderModel]) -> list[OrderModel]:
74
+ """Only THIS tenant's orders — no manual WHERE."""
75
+ return await repo.list() # WHERE tenant_id = <bound tenant>
76
+
77
+
78
+ async def create_order(
79
+ repo: TenantScopedRepository[OrderModel], total: int
80
+ ) -> OrderModel:
81
+ """tenant_id is stamped automatically on insert."""
82
+ return await repo.add(OrderModel(total=total))
83
+ ```
84
+
85
+ ### Cross-tenant access is impossible, even by id
86
+
87
+ `get_by_id`, `delete` and `delete_batch` are scoped too. An id from another
88
+ tenant simply **doesn't match** — indistinguishable from a row that never
89
+ existed:
90
+
91
+ ```python
92
+ from uuid import UUID
93
+
94
+ from tempest_fastapi_sdk import TenantScopedRepository
95
+
96
+ from src.db.models import OrderModel
97
+
98
+
99
+ async def fetch(repo: TenantScopedRepository[OrderModel], order_id: UUID) -> OrderModel:
100
+ """Raises NotFound if the order belongs to ANOTHER tenant — no existence leak."""
101
+ return await repo.get_by_id(order_id)
102
+ ```
103
+
104
+ `delete_many({})` deletes only **this** tenant's rows, never the whole
105
+ table — the tenant predicate is always added.
106
+
107
+ !!! warning "Raw queries are your responsibility"
108
+ A subclass that builds its own `select(...)` without going through
109
+ `_apply_filters` — or a pre-built `query=` passed to `paginate` — is
110
+ **not** auto-scoped. In those cases, add
111
+ `.where(self.tenant_column == self.tenant_id)` yourself.
112
+
113
+ ## Recap
114
+
115
+ - The model declares `tenant_id` (or another column, via `tenant_field=`).
116
+ - `TenantScopedRepository(session, model=..., tenant_id=...)` injects the
117
+ filter into every read and stamps every write.
118
+ - `get_by_id` / `delete` / `delete_batch` / `delete_many` are scoped —
119
+ cross-tenant access is impossible through the repository methods.
120
+ - The constructor validates the tenant column exists at boot.
@@ -0,0 +1,120 @@
1
+ # Multi-tenant (TenantScopedRepository)
2
+
3
+ Num banco multi-tenant de **schema compartilhado**, as linhas de todos os
4
+ tenants moram na mesma tabela, separadas por uma coluna `tenant_id`. O
5
+ perigo é claro: esquecer **um** `WHERE tenant_id = ?` e o tenant A lê (ou
6
+ apaga) os dados do tenant B. `TenantScopedRepository` tira esse risco da
7
+ mesa — você amarra o `tenant_id` na construção e ele injeta o filtro em
8
+ **toda** leitura e carimba em **toda** escrita. Os call sites não têm como
9
+ errar.
10
+
11
+ !!! info "Onde isso encaixa"
12
+ É um `BaseRepository` que se comporta igualzinho — mesma API
13
+ ([Banco de dados](database.md)). A diferença é invisível pro chamador:
14
+ o escopo de tenant é automático.
15
+
16
+ ## 1. O modelo precisa da coluna de tenant
17
+
18
+ ```python
19
+ from uuid import UUID
20
+
21
+ from sqlalchemy import String, Uuid
22
+ from sqlalchemy.orm import Mapped, mapped_column
23
+
24
+ from tempest_fastapi_sdk import BaseModel
25
+
26
+
27
+ class OrderModel(BaseModel):
28
+ """Pedido — isolado por tenant."""
29
+
30
+ __tablename__ = "order"
31
+
32
+ tenant_id: Mapped[UUID] = mapped_column(Uuid(), nullable=False, index=True)
33
+ total: Mapped[int] = mapped_column(nullable=False)
34
+ ```
35
+
36
+ ## 2. Construa o repositório amarrado ao tenant
37
+
38
+ O `tenant_id` normalmente vem do JWT / sessão / header do request:
39
+
40
+ ```python
41
+ from uuid import UUID
42
+
43
+ from sqlalchemy.ext.asyncio import AsyncSession
44
+
45
+ from tempest_fastapi_sdk import TenantScopedRepository
46
+
47
+ from src.db.models import OrderModel
48
+
49
+
50
+ def get_order_repo(
51
+ session: AsyncSession, tenant_id: UUID
52
+ ) -> TenantScopedRepository[OrderModel]:
53
+ """Repositório de pedidos travado no tenant do request."""
54
+ return TenantScopedRepository(session, model=OrderModel, tenant_id=tenant_id)
55
+ ```
56
+
57
+ Se o modelo não tiver a coluna `tenant_id`, o construtor levanta
58
+ `AttributeError` na hora — você descobre o erro no boot, não em produção.
59
+ Coluna com outro nome? Passe `tenant_field="org_id"`.
60
+
61
+ ## 3. Use como qualquer repositório
62
+
63
+ Toda leitura já vem filtrada; toda escrita já vem carimbada:
64
+
65
+ ```python
66
+ from uuid import UUID
67
+
68
+ from tempest_fastapi_sdk import TenantScopedRepository
69
+
70
+ from src.db.models import OrderModel
71
+
72
+
73
+ async def list_orders(repo: TenantScopedRepository[OrderModel]) -> list[OrderModel]:
74
+ """Só os pedidos DESTE tenant — sem WHERE manual."""
75
+ return await repo.list() # WHERE tenant_id = <tenant amarrado>
76
+
77
+
78
+ async def create_order(
79
+ repo: TenantScopedRepository[OrderModel], total: int
80
+ ) -> OrderModel:
81
+ """tenant_id é carimbado automaticamente no insert."""
82
+ return await repo.add(OrderModel(total=total))
83
+ ```
84
+
85
+ ### Acesso cruzado é impossível, mesmo por id
86
+
87
+ `get_by_id`, `delete` e `delete_batch` também são escopados. Um id de outro
88
+ tenant simplesmente **não casa** — é indistinguível de uma linha que nunca
89
+ existiu:
90
+
91
+ ```python
92
+ from uuid import UUID
93
+
94
+ from tempest_fastapi_sdk import TenantScopedRepository
95
+
96
+ from src.db.models import OrderModel
97
+
98
+
99
+ async def fetch(repo: TenantScopedRepository[OrderModel], order_id: UUID) -> OrderModel:
100
+ """Levanta NotFound se o pedido for de OUTRO tenant — sem vazar existência."""
101
+ return await repo.get_by_id(order_id)
102
+ ```
103
+
104
+ `delete_many({})` apaga só as linhas **deste** tenant, nunca a tabela
105
+ inteira — o predicado de tenant é sempre adicionado.
106
+
107
+ !!! warning "Queries cruas são responsabilidade sua"
108
+ Uma subclasse que monta o próprio `select(...)` sem passar por
109
+ `_apply_filters` — ou um `query=` pré-montado passado pro `paginate` —
110
+ **não** é escopado automaticamente. Nesses casos, adicione
111
+ `.where(self.tenant_column == self.tenant_id)` você mesmo.
112
+
113
+ ## Recap
114
+
115
+ - O modelo declara `tenant_id` (ou outra coluna, via `tenant_field=`).
116
+ - `TenantScopedRepository(session, model=..., tenant_id=...)` injeta o
117
+ filtro em toda leitura e carimba toda escrita.
118
+ - `get_by_id` / `delete` / `delete_batch` / `delete_many` são escopados —
119
+ acesso cruzado entre tenants é impossível pelos métodos do repositório.
120
+ - Construtor valida a existência da coluna de tenant no boot.
@@ -31,6 +31,7 @@ Gerada automaticamente a partir das docstrings do SDK via [`mkdocstrings`](https
31
31
  ::: tempest_fastapi_sdk.db.user_recovery_code_model.BaseUserRecoveryCodeModel
32
32
  ::: tempest_fastapi_sdk.db.user_recovery_code_model.make_user_recovery_code_model
33
33
  ::: tempest_fastapi_sdk.db.repository.BaseRepository
34
+ ::: tempest_fastapi_sdk.db.tenant.TenantScopedRepository
34
35
  ::: tempest_fastapi_sdk.db.mixins.SoftDeleteMixin
35
36
  ::: tempest_fastapi_sdk.db.mixins.AuditMixin
36
37
  ::: tempest_fastapi_sdk.db.mixins.MFAMixin
@@ -86,6 +86,7 @@ plugins:
86
86
  Tutorial: Tutorial
87
87
  Receitas: Recipes
88
88
  Banco de dados: Database
89
+ Multi-tenant: Multi-tenant
89
90
  Camada HTTP: HTTP layer
90
91
  "HTTP client (saída)": "HTTP client (outbound)"
91
92
  Cache: Cache
@@ -200,6 +201,7 @@ nav:
200
201
  - Receitas:
201
202
  - recipes/index.md
202
203
  - Banco de dados: recipes/database.md
204
+ - Multi-tenant: recipes/multi-tenant.md
203
205
  - Camada HTTP: recipes/http.md
204
206
  - "HTTP client (saída)": recipes/http-client.md
205
207
  - Cache: recipes/cache.md
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tempest-fastapi-sdk"
3
- version = "0.44.0"
3
+ version = "0.45.0"
4
4
  description = "Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -109,6 +109,7 @@ from tempest_fastapi_sdk.db import (
109
109
  OutboxStatus,
110
110
  SlowQueryLogger,
111
111
  SoftDeleteMixin,
112
+ TenantScopedRepository,
112
113
  UserTokenPurpose,
113
114
  compose_hooks,
114
115
  make_user_recovery_code_model,
@@ -247,7 +248,7 @@ from tempest_fastapi_sdk.websockets import (
247
248
  make_websocket_router,
248
249
  )
249
250
 
250
- __version__: str = "0.44.0"
251
+ __version__: str = "0.45.0"
251
252
 
252
253
  __all__: list[str] = [
253
254
  "BASE_COLUMN_ORDER",
@@ -387,6 +388,7 @@ __all__: list[str] = [
387
388
  "SystemMetrics",
388
389
  "TOTPHelper",
389
390
  "TaskIQSettings",
391
+ "TenantScopedRepository",
390
392
  "ThrottleBackend",
391
393
  "ThrottleStatus",
392
394
  "TokenSettings",
@@ -26,6 +26,9 @@ from tempest_fastapi_sdk.db.outbox import OutboxRelay as OutboxRelay
26
26
  from tempest_fastapi_sdk.db.outbox import OutboxStatus as OutboxStatus
27
27
  from tempest_fastapi_sdk.db.repository import BaseRepository as BaseRepository
28
28
  from tempest_fastapi_sdk.db.slow_query import SlowQueryLogger as SlowQueryLogger
29
+ from tempest_fastapi_sdk.db.tenant import (
30
+ TenantScopedRepository as TenantScopedRepository,
31
+ )
29
32
  from tempest_fastapi_sdk.db.user_model import BaseUserModel as BaseUserModel
30
33
  from tempest_fastapi_sdk.db.user_recovery_code_model import (
31
34
  BaseUserRecoveryCodeModel as BaseUserRecoveryCodeModel,
@@ -58,6 +61,7 @@ __all__: list[str] = [
58
61
  "OutboxStatus",
59
62
  "SlowQueryLogger",
60
63
  "SoftDeleteMixin",
64
+ "TenantScopedRepository",
61
65
  "UserTokenPurpose",
62
66
  "compose_hooks",
63
67
  "make_user_recovery_code_model",