tempest-fastapi-sdk 0.61.0__tar.gz → 0.63.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 (424) hide show
  1. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/CHANGELOG.md +58 -0
  2. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/PKG-INFO +10 -1
  3. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/README.md +9 -0
  4. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/migration.en.md +30 -0
  5. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/migration.md +30 -0
  6. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/database.en.md +18 -0
  7. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/database.md +18 -0
  8. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/pyproject.toml +1 -1
  9. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/__init__.py +1 -1
  10. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/dependencies/auth.py +60 -16
  11. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/service.py +31 -4
  12. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/repository.py +23 -3
  13. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/pagination.py +56 -0
  14. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_service.py +63 -1
  15. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_repository.py +32 -1
  16. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_cursor_pagination.py +14 -0
  17. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_pagination.py +17 -0
  18. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/uv.lock +1 -1
  19. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/.github/workflows/ci.yml +0 -0
  20. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/.github/workflows/docs.yml +0 -0
  21. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/.github/workflows/release-pypi.yml +0 -0
  22. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/.gitignore +0 -0
  23. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/.python-version +0 -0
  24. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/CLAUDE.md +0 -0
  25. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/Makefile +0 -0
  26. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/architecture.en.md +0 -0
  27. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/architecture.md +0 -0
  28. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/changelog.en.md +0 -0
  29. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/changelog.md +0 -0
  30. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/contributing.en.md +0 -0
  31. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/contributing.md +0 -0
  32. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/index.en.md +0 -0
  33. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/index.md +0 -0
  34. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/installation.en.md +0 -0
  35. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/installation.md +0 -0
  36. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/index.en.md +0 -0
  37. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/index.md +0 -0
  38. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/api.en.md +0 -0
  39. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/api.md +0 -0
  40. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/business-rules.en.md +0 -0
  41. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/business-rules.md +0 -0
  42. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/domain.en.md +0 -0
  43. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/domain.md +0 -0
  44. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/flows.en.md +0 -0
  45. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/flows.md +0 -0
  46. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/index.en.md +0 -0
  47. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/index.md +0 -0
  48. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/admin.en.md +0 -0
  49. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/admin.md +0 -0
  50. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/audit-trail.en.md +0 -0
  51. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/audit-trail.md +0 -0
  52. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/auth-flow.en.md +0 -0
  53. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/auth-flow.md +0 -0
  54. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/br-helpers.en.md +0 -0
  55. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/br-helpers.md +0 -0
  56. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cache.en.md +0 -0
  57. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cache.md +0 -0
  58. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cli.en.md +0 -0
  59. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cli.md +0 -0
  60. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/deploy-safety.en.md +0 -0
  61. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/deploy-safety.md +0 -0
  62. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/downloads.en.md +0 -0
  63. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/downloads.md +0 -0
  64. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/email.en.md +0 -0
  65. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/email.md +0 -0
  66. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/feature-flags.en.md +0 -0
  67. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/feature-flags.md +0 -0
  68. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http-client.en.md +0 -0
  69. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http-client.md +0 -0
  70. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http.en.md +0 -0
  71. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http.md +0 -0
  72. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/idempotency.en.md +0 -0
  73. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/idempotency.md +0 -0
  74. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/index.en.md +0 -0
  75. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/index.md +0 -0
  76. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/logging.en.md +0 -0
  77. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/logging.md +0 -0
  78. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/metrics.en.md +0 -0
  79. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/metrics.md +0 -0
  80. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/mfa.en.md +0 -0
  81. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/mfa.md +0 -0
  82. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/multi-tenant.en.md +0 -0
  83. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/multi-tenant.md +0 -0
  84. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/observability.en.md +0 -0
  85. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/observability.md +0 -0
  86. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/offline-sync.en.md +0 -0
  87. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/offline-sync.md +0 -0
  88. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/outbox.en.md +0 -0
  89. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/outbox.md +0 -0
  90. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/queue-tasks.en.md +0 -0
  91. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/queue-tasks.md +0 -0
  92. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/realtime.en.md +0 -0
  93. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/realtime.md +0 -0
  94. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/security.en.md +0 -0
  95. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/security.md +0 -0
  96. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/sessions.en.md +0 -0
  97. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/sessions.md +0 -0
  98. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/storage.en.md +0 -0
  99. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/storage.md +0 -0
  100. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/testing.en.md +0 -0
  101. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/testing.md +0 -0
  102. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/uploads.en.md +0 -0
  103. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/uploads.md +0 -0
  104. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/utilities.en.md +0 -0
  105. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/utilities.md +0 -0
  106. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/webpush.en.md +0 -0
  107. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/webpush.md +0 -0
  108. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/websocket.en.md +0 -0
  109. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/websocket.md +0 -0
  110. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/reference.en.md +0 -0
  111. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/reference.md +0 -0
  112. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/roadmap.en.md +0 -0
  113. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/roadmap.md +0 -0
  114. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/tutorial.en.md +0 -0
  115. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/docs/tutorial.md +0 -0
  116. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/mkdocs.yml +0 -0
  117. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/scripts/extract_recipe.py +0 -0
  118. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
  119. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
  120. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/config.py +0 -0
  121. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
  122. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/router.py +0 -0
  123. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/session.py +0 -0
  124. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/site.py +0 -0
  125. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
  126. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
  127. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
  128. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
  129. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
  130. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
  131. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
  132. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
  133. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
  134. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
  135. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
  136. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
  137. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
  138. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
  139. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
  140. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
  141. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
  142. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
  143. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
  144. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
  145. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
  146. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
  147. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
  148. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
  149. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
  150. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
  151. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
  152. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/server.py +0 -0
  153. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/static.py +0 -0
  154. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
  155. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
  156. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/__init__.py +0 -0
  157. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
  158. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/locale.py +0 -0
  159. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
  160. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/router.py +0 -0
  161. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
  162. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
  163. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
  164. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
  165. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
  166. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
  167. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
  168. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
  169. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
  170. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
  171. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
  172. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
  173. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
  174. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
  175. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
  176. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
  177. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
  178. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
  179. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
  180. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
  181. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
  182. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
  183. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
  184. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
  185. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
  186. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
  187. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
  188. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
  189. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
  190. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
  191. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
  192. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
  193. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
  194. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
  195. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
  196. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
  197. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
  198. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
  199. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
  200. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
  201. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
  202. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
  203. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
  204. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
  205. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
  206. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
  207. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/db.py +0 -0
  208. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
  209. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
  210. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
  211. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/main.py +0 -0
  212. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/new.py +0 -0
  213. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
  214. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
  215. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/user.py +0 -0
  216. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
  217. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
  218. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
  219. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/context.py +0 -0
  220. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/enums.py +0 -0
  221. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/logging.py +0 -0
  222. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
  223. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
  224. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
  225. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
  226. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/audit.py +0 -0
  227. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/connection.py +0 -0
  228. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
  229. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
  230. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/model.py +0 -0
  231. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
  232. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
  233. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
  234. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
  235. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
  236. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
  237. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
  238. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
  239. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
  240. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
  241. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
  242. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
  243. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
  244. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
  245. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
  246. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
  247. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
  248. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
  249. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
  250. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
  251. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/service.py +0 -0
  252. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/py.typed +0 -0
  253. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
  254. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
  255. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
  256. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
  257. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
  258. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
  259. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
  260. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
  261. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/services/base.py +0 -0
  262. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
  263. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
  264. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
  265. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
  266. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
  267. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
  268. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
  269. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
  270. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/settings/base.py +0 -0
  271. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/settings/mixins.py +0 -0
  272. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sse/__init__.py +0 -0
  273. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sse/event_stream.py +0 -0
  274. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
  275. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
  276. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
  277. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
  278. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
  279. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
  280. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/testing/database.py +0 -0
  281. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
  282. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
  283. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
  284. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
  285. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
  286. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/download.py +0 -0
  287. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/email.py +0 -0
  288. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
  289. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
  290. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
  291. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/log.py +0 -0
  292. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
  293. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
  294. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/password.py +0 -0
  295. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
  296. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
  297. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
  298. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
  299. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
  300. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
  301. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
  302. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
  303. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
  304. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
  305. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
  306. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
  307. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/__init__.py +0 -0
  308. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/__init__.py +0 -0
  309. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_auth.py +0 -0
  310. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_forms.py +0 -0
  311. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_logs_nav.py +0 -0
  312. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_mfa.py +0 -0
  313. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_router.py +0 -0
  314. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_site.py +0 -0
  315. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_user_model.py +0 -0
  316. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/__init__.py +0 -0
  317. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_body_size.py +0 -0
  318. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_cookies.py +0 -0
  319. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_cors.py +0 -0
  320. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_csrf.py +0 -0
  321. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_dependencies_auth.py +0 -0
  322. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_graceful.py +0 -0
  323. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_handlers.py +0 -0
  324. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_health_router.py +0 -0
  325. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_idempotency.py +0 -0
  326. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_jwt_dependency.py +0 -0
  327. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_logs_router.py +0 -0
  328. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_oauth.py +0 -0
  329. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_prometheus.py +0 -0
  330. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_rate_limit.py +0 -0
  331. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_rate_limit_extras.py +0 -0
  332. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_request_id_middleware.py +0 -0
  333. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_role_dependency.py +0 -0
  334. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_server.py +0 -0
  335. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_static.py +0 -0
  336. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_tool_spec.py +0 -0
  337. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_tracing.py +0 -0
  338. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_webhooks.py +0 -0
  339. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_webhooks_rsa.py +0 -0
  340. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/__init__.py +0 -0
  341. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_guards.py +0 -0
  342. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_locale.py +0 -0
  343. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_mfa.py +0 -0
  344. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/__init__.py +0 -0
  345. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/test_decorator.py +0 -0
  346. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/test_invalidation.py +0 -0
  347. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/test_redis_manager.py +0 -0
  348. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/__init__.py +0 -0
  349. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_db.py +0 -0
  350. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_db_seed.py +0 -0
  351. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_docker_compose.py +0 -0
  352. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_generate.py +0 -0
  353. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_main.py +0 -0
  354. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_secrets.py +0 -0
  355. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_user.py +0 -0
  356. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/conftest.py +0 -0
  357. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/controllers/__init__.py +0 -0
  358. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/controllers/test_base.py +0 -0
  359. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/core/__init__.py +0 -0
  360. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/core/test_context.py +0 -0
  361. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/core/test_enums.py +0 -0
  362. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/core/test_logging.py +0 -0
  363. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/__init__.py +0 -0
  364. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_alembic_hooks.py +0 -0
  365. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_audit.py +0 -0
  366. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_bulk_ops.py +0 -0
  367. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_connection.py +0 -0
  368. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_migrations.py +0 -0
  369. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_mixins.py +0 -0
  370. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_model.py +0 -0
  371. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_outbox.py +0 -0
  372. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_safe_upgrade.py +0 -0
  373. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_slow_query.py +0 -0
  374. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_tenant.py +0 -0
  375. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/exceptions/__init__.py +0 -0
  376. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/exceptions/test_exceptions.py +0 -0
  377. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/exceptions/test_i18n.py +0 -0
  378. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/flags/__init__.py +0 -0
  379. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/flags/test_flags.py +0 -0
  380. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/queue/__init__.py +0 -0
  381. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/queue/test_manager.py +0 -0
  382. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/__init__.py +0 -0
  383. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_base.py +0 -0
  384. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_link_headers.py +0 -0
  385. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_response.py +0 -0
  386. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/services/__init__.py +0 -0
  387. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/services/test_base.py +0 -0
  388. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/sessions/__init__.py +0 -0
  389. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/sessions/test_sessions.py +0 -0
  390. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/settings/__init__.py +0 -0
  391. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/settings/test_base.py +0 -0
  392. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/settings/test_mixins.py +0 -0
  393. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/sse/__init__.py +0 -0
  394. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/sse/test_event_stream.py +0 -0
  395. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/storage/__init__.py +0 -0
  396. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/storage/test_minio_client.py +0 -0
  397. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/tasks/__init__.py +0 -0
  398. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/tasks/test_manager.py +0 -0
  399. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/tasks/test_scheduler.py +0 -0
  400. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/testing/__init__.py +0 -0
  401. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/testing/test_database.py +0 -0
  402. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/__init__.py +0 -0
  403. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_client_ip.py +0 -0
  404. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_datetime.py +0 -0
  405. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_dict.py +0 -0
  406. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_download.py +0 -0
  407. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_email.py +0 -0
  408. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_http_client.py +0 -0
  409. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_jwt.py +0 -0
  410. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_lazy_extras.py +0 -0
  411. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_locations.py +0 -0
  412. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_log.py +0 -0
  413. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_metrics.py +0 -0
  414. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_opaque_token.py +0 -0
  415. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_password.py +0 -0
  416. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_regex.py +0 -0
  417. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_storage_backends.py +0 -0
  418. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_throttle.py +0 -0
  419. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_upload.py +0 -0
  420. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/webpush/__init__.py +0 -0
  421. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/webpush/test_dispatcher.py +0 -0
  422. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/webpush/test_schemas.py +0 -0
  423. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/websockets/__init__.py +0 -0
  424. {tempest_fastapi_sdk-0.61.0 → tempest_fastapi_sdk-0.63.0}/tests/websockets/test_hub_and_router.py +0 -0
@@ -5,6 +5,64 @@ 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.63.0] — 2026-06-21
9
+
10
+ ### Changed
11
+
12
+ - **`UserAuthService.current_user_dependency()` now loads the authenticated
13
+ user on the request-scoped session** (`db.session_dependency` by default)
14
+ instead of opening its own short-lived session through `load_user`.
15
+ Previously the returned `UserModel` was **detached** — mutating it and
16
+ committing/refreshing on the request's repository session raised
17
+ `InvalidRequestError: Instance is not persistent within this Session`,
18
+ and lazy-relationship access raised `DetachedInstanceError`. The user is
19
+ now attached to the same session repositories use. **Breaking** only for
20
+ apps whose repositories do not share the auth service's session callable;
21
+ pass `session_dependency=` to point both at the same provider. See the
22
+ **Migration guide** (`docs/migration.md`). The single-argument `user_loader` path
23
+ of `make_jwt_user_dependency` is unchanged; the new behavior is opt-in via
24
+ the new `session_dependency=` parameter (which `current_user_dependency`
25
+ now passes by default).
26
+ - **`BaseRepository.resolve()` re-attaches detached instances** via
27
+ `session.merge()` instead of returning them as-is. A detached model passed
28
+ to a mutating service is brought back into the active session, so the
29
+ subsequent `update()` commits instead of raising. `merge` issues a
30
+ `SELECT` only when the row is not already in the session's identity map.
31
+
32
+ ### Added
33
+
34
+ - **`make_jwt_user_dependency(..., session_dependency=...)`** — when given a
35
+ request-scoped session provider, the dependency injects it and calls the
36
+ two-argument loader `user_loader(subject, session)`, sharing the session
37
+ with the request's repositories.
38
+ - **`UserAuthService.current_user_dependency(session_dependency=...)`** —
39
+ override the session provider shared with repositories (defaults to
40
+ `self.db.session_dependency`). Now raises `RuntimeError` eagerly when the
41
+ service was built without `db=`.
42
+
43
+ ## [0.62.0] — 2026-06-20
44
+
45
+ ### Added
46
+
47
+ - **`BasePaginationFilterSchema.get_pagination_conditions()`** and
48
+ **`CursorPaginationFilterSchema.get_pagination_conditions()`** — the
49
+ counterpart to `get_conditions()`. Where `get_conditions()` strips the
50
+ pagination keys to expose the domain filters, this returns **only** the
51
+ pagination/sort keys (`page`/`page_size`/`order_by`/`ascending` for
52
+ offset, `cursor`/`limit`/`order_by`/`ascending` for cursor). A service
53
+ can now forward a filter schema to `paginate` / `cursor_paginate`
54
+ without manually unpacking the model:
55
+
56
+ ```python
57
+ data = await repo.paginate(
58
+ filters=f.get_conditions(),
59
+ **f.get_pagination_conditions(),
60
+ )
61
+ ```
62
+
63
+ This replaces the `**filter_schema` idiom, which leaked domain filters
64
+ (e.g. `is_active`) into keyword arguments the repository does not accept.
65
+
8
66
  ## [0.61.0] — 2026-06-15
9
67
 
10
68
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tempest-fastapi-sdk
3
- Version: 0.61.0
3
+ Version: 0.63.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
@@ -1167,6 +1167,15 @@ async def me(current: UserModel = Depends(get_current_user)) -> UserResponseSche
1167
1167
  > get_current_user = auth_service.current_user_dependency()
1168
1168
  > get_current_user_or_none = auth_service.current_user_dependency(soft=True)
1169
1169
  > ```
1170
+ >
1171
+ > The authenticated user is loaded on the **request-scoped session**
1172
+ > (`db.session_dependency`), so it is attached to the same session your
1173
+ > repositories use — you can mutate it and `commit`/`refresh` without an
1174
+ > `InvalidRequestError: Instance is not persistent within this Session`.
1175
+ > Keep one shared session callable (`get_session = db.session_dependency`)
1176
+ > for FastAPI to deduplicate them; if your repositories depend on a
1177
+ > different `get_session` wrapper, pass it as
1178
+ > `current_user_dependency(session_dependency=get_session)`.
1170
1179
 
1171
1180
  #### Soft auth (optional user)
1172
1181
 
@@ -1064,6 +1064,15 @@ async def me(current: UserModel = Depends(get_current_user)) -> UserResponseSche
1064
1064
  > get_current_user = auth_service.current_user_dependency()
1065
1065
  > get_current_user_or_none = auth_service.current_user_dependency(soft=True)
1066
1066
  > ```
1067
+ >
1068
+ > The authenticated user is loaded on the **request-scoped session**
1069
+ > (`db.session_dependency`), so it is attached to the same session your
1070
+ > repositories use — you can mutate it and `commit`/`refresh` without an
1071
+ > `InvalidRequestError: Instance is not persistent within this Session`.
1072
+ > Keep one shared session callable (`get_session = db.session_dependency`)
1073
+ > for FastAPI to deduplicate them; if your repositories depend on a
1074
+ > different `get_session` wrapper, pass it as
1075
+ > `current_user_dependency(session_dependency=get_session)`.
1067
1076
 
1068
1077
  #### Soft auth (optional user)
1069
1078
 
@@ -2,6 +2,36 @@
2
2
 
3
3
  Breaking-change walkthroughs grouped by minor release. Stick to the version that matches what you're upgrading **from**.
4
4
 
5
+ ## 0.63.0 — authenticated user loaded on the request session
6
+
7
+ Before 0.63.0, `UserAuthService.current_user_dependency()` loaded the authenticated user through `load_user`, which opened its **own** session (via `db.get_session_context()`) and closed it on exit. The `UserModel` handed to the route was therefore **detached**: mutating it and calling `commit`/`refresh` on the request session (the one your repositories use) raised
8
+ `InvalidRequestError: Instance is not persistent within this Session`.
9
+
10
+ From 0.63.0 the dependency loads the user on the **request session** (`db.session_dependency` by default) via `get_user(subject, session)`. The user is attached to the same session repositories use, so lazy-relationship reads and writes work without re-attaching anything.
11
+
12
+ !!! warning "Compatibility"
13
+ The auth dependency and your repositories must share the **same** session callable for FastAPI's sub-dependency cache to deduplicate them. The recommended pattern is already covered:
14
+
15
+ ```python
16
+ # resources.py
17
+ get_session = db.session_dependency # one object, reused
18
+ ```
19
+
20
+ If you wrap the session in your own provider (`async def get_session(): ...`), pass it explicitly, otherwise the dependency opens a second session and the user is detached again:
21
+
22
+ ```python
23
+ get_current_user = auth.current_user_dependency(session_dependency=get_session)
24
+ ```
25
+
26
+ !!! info "Extra safety net"
27
+ `BaseRepository.resolve()` now re-attaches detached instances via `session.merge()`. Even if some flow still hands in a detached user, `resolve` brings it back into the active session instead of breaking — so services that worked around this (re-fetch by id before mutating) can drop the workaround.
28
+
29
+ ### Verify
30
+
31
+ - Drop any "re-fetch by id before mutating the authenticated user" workaround — it's no longer needed.
32
+ - A single-argument `user_loader` passed to `make_jwt_user_dependency` keeps working. To share the request session, pass `session_dependency=` and use a two-argument loader `(subject, session)`.
33
+
34
+ ## 0.8.0 — `ServerSettings` rename
5
35
 
6
36
  0.8.0 renames every field on `ServerSettings`, extracts log fields to a new `LogSettings` mixin, and adds eleven other primitives. The renames are the only **breaking** changes — every new primitive is opt-in.
7
37
 
@@ -2,6 +2,36 @@
2
2
 
3
3
  Passo a passo das mudanças que quebram compatibilidade, agrupadas por release minor. Siga a versão que casa com aquela **de onde** você está atualizando.
4
4
 
5
+ ## 0.63.0 — usuário autenticado carregado na sessão de request
6
+
7
+ Antes da 0.63.0, `UserAuthService.current_user_dependency()` carregava o usuário autenticado chamando `load_user`, que abria a **própria** sessão (via `db.get_session_context()`) e a fechava ao terminar. O `UserModel` entregue à rota ficava **detached**: mutá-lo e dar `commit`/`refresh` na sessão de request (a dos seus repositories) levantava
8
+ `InvalidRequestError: Instance is not persistent within this Session`.
9
+
10
+ A partir da 0.63.0 a dependência carrega o usuário na **sessão de request** (`db.session_dependency` por padrão), via `get_user(subject, session)`. O usuário fica anexado à mesma sessão que os repositories usam, então leituras de relacionamentos lazy e escritas funcionam sem reanexar nada.
11
+
12
+ !!! warning "Compatibilidade"
13
+ A dependência de auth e seus repositories precisam compartilhar o **mesmo callable** de sessão para o cache de sub-dependências do FastAPI casar. Quem segue o padrão recomendado já está coberto:
14
+
15
+ ```python
16
+ # resources.py
17
+ get_session = db.session_dependency # um único objeto, reutilizado
18
+ ```
19
+
20
+ Se você embrulha a sessão num provider próprio (`async def get_session(): ...`), passe-o explicitamente para a dependência, senão ela abre uma segunda sessão e o usuário volta a ficar detached:
21
+
22
+ ```python
23
+ get_current_user = auth.current_user_dependency(session_dependency=get_session)
24
+ ```
25
+
26
+ !!! info "Defesa adicional"
27
+ `BaseRepository.resolve()` agora reanexa instâncias detached via `session.merge()`. Mesmo que algum fluxo ainda receba um usuário detached, o `resolve` o traz de volta à sessão ativa em vez de quebrar — então serviços que faziam workarounds manuais (re-fetch por id antes de mutar) podem removê-los.
28
+
29
+ ### Verifique
30
+
31
+ - Remova qualquer workaround do tipo "re-fetch por id antes de mutar o usuário autenticado" — não é mais necessário.
32
+ - Se você passava um `user_loader` de um argumento para `make_jwt_user_dependency`, ele continua funcionando. Para compartilhar a sessão de request, passe `session_dependency=` e use um loader de dois argumentos `(subject, session)`.
33
+
34
+ ## 0.8.0 — renomeação de `ServerSettings`
5
35
 
6
36
  A 0.8.0 renomeia todos os campos de `ServerSettings`, extrai os campos de log para um novo mixin `LogSettings` e adiciona onze outros primitivos. As renomeações são as únicas mudanças **que quebram** — todo primitivo novo é opt-in.
7
37
 
@@ -650,6 +650,24 @@ class UserRepository(BaseRepository[UserModel]):
650
650
  query, so custom joins still report a correct total. When `order_by` is
651
651
  `None`, it orders by `created_at desc`.
652
652
 
653
+ !!! tip "Forward the schema without unpacking it by hand"
654
+ The `get_conditions()` / `get_pagination_conditions()` pair covers both
655
+ sides of the filter: the former returns only the domain filters, the
656
+ latter only the pagination keys (`page`, `page_size`, `order_by`,
657
+ `ascending`). The service forwards the filter straight through, no
658
+ `**f` — which would leak domain filters (`is_active`, etc.) as kwargs
659
+ the repository does not accept:
660
+
661
+ ```python
662
+ data = await repo.paginate(
663
+ filters=f.get_conditions(),
664
+ **f.get_pagination_conditions(),
665
+ )
666
+ ```
667
+
668
+ `CursorPaginationFilterSchema` exposes the same pair (with `cursor` /
669
+ `limit` instead of `page` / `page_size`).
670
+
653
671
  ### Cursor — when the table is large
654
672
 
655
673
  Cursor pagination scales better than offset on large tables (no
@@ -651,6 +651,24 @@ class UserRepository(BaseRepository[UserModel]):
651
651
  filtrada, então joins custom ainda reportam total correto. Quando
652
652
  `order_by` é `None`, ordena por `created_at desc`.
653
653
 
654
+ !!! tip "Encaminhe o schema sem desempacotar à mão"
655
+ O par `get_conditions()` / `get_pagination_conditions()` cobre os dois
656
+ lados do filtro: o primeiro devolve só os filtros de domínio, o segundo
657
+ só as chaves de paginação (`page`, `page_size`, `order_by`,
658
+ `ascending`). Assim o service repassa o filtro direto, sem `**f` — que
659
+ vazaria filtros de domínio (`is_active`, etc.) como kwargs que o
660
+ repository não aceita:
661
+
662
+ ```python
663
+ data = await repo.paginate(
664
+ filters=f.get_conditions(),
665
+ **f.get_pagination_conditions(),
666
+ )
667
+ ```
668
+
669
+ `CursorPaginationFilterSchema` tem o mesmo par (com `cursor` / `limit`
670
+ no lugar de `page` / `page_size`).
671
+
654
672
  ### Cursor — quando a tabela é grande
655
673
 
656
674
  A paginação por cursor escala melhor que offset em tabelas grandes (sem
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tempest-fastapi-sdk"
3
- version = "0.61.0"
3
+ version = "0.63.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"
@@ -301,7 +301,7 @@ from tempest_fastapi_sdk.websockets import (
301
301
  make_websocket_router,
302
302
  )
303
303
 
304
- __version__: str = "0.61.0"
304
+ __version__: str = "0.63.0"
305
305
 
306
306
  __all__: list[str] = [
307
307
  "BASE_COLUMN_ORDER",
@@ -139,6 +139,7 @@ def make_jwt_user_dependency(
139
139
  bearer_scheme: HTTPBearer | None = None,
140
140
  subject_claim: str = "sub",
141
141
  error_message: str = "Authorization token is missing or invalid",
142
+ session_dependency: Callable[..., Any] | None = None,
142
143
  ) -> Callable[..., Coroutine[Any, Any, Any]]:
143
144
  """Build a FastAPI dependency that returns the authenticated user.
144
145
 
@@ -150,15 +151,33 @@ def make_jwt_user_dependency(
150
151
  4. Awaits ``user_loader(<id>)`` and returns whatever it yields.
151
152
 
152
153
  ``user_loader`` is the single seam where the service maps
153
- ``payload[subject_claim]`` to an actual user. It's an async
154
- callable (so it can open / close its own DB session) — the SDK
155
- doesn't impose a session shape.
154
+ ``payload[subject_claim]`` to an actual user.
155
+
156
+ **Session sharing.** When ``session_dependency`` is given, the
157
+ returned dependency declares it as a sub-dependency and calls the
158
+ two-argument ``user_loader(subject, session)`` with the
159
+ **request-scoped** session. Because FastAPI caches a sub-dependency
160
+ by its callable within a single request, the authenticated user is
161
+ loaded on the *same* session the request's repositories use — so the
162
+ instance stays attached and can be mutated / refreshed without the
163
+ ``InvalidRequestError: Instance is not persistent within this
164
+ Session`` that a per-loader private session would cause. Pass the
165
+ **exact** callable your repositories depend on (e.g.
166
+ ``db.session_dependency``); a different wrapper would resolve to a
167
+ second, distinct session and defeat the sharing.
168
+
169
+ When ``session_dependency`` is ``None`` the loader is called with a
170
+ single argument (``user_loader(subject)``) and owns its own session
171
+ lifecycle — useful outside a request scope, but it yields a
172
+ **detached** instance.
156
173
 
157
174
  Args:
158
175
  tokens (JWTUtils): The JWT helper used to verify the token.
159
176
  user_loader (Callable[..., Coroutine[Any, Any, Any]]): Async
160
177
  callable that receives the subject (typically the user id
161
- as a string) and returns the loaded user. Raise
178
+ as a string) and returns the loaded user. When
179
+ ``session_dependency`` is set it is called as
180
+ ``user_loader(subject, session)``. Raise
162
181
  :class:`UnauthorizedException` or
163
182
  :class:`NotFoundException` from inside the loader when the
164
183
  user no longer exists.
@@ -169,6 +188,10 @@ def make_jwt_user_dependency(
169
188
  Defaults to ``"sub"``.
170
189
  error_message (str): Message attached to the raised
171
190
  :class:`UnauthorizedException` when ``soft`` is ``False``.
191
+ session_dependency (Callable[..., Any] | None): The
192
+ request-scoped session provider to share with repositories.
193
+ When set, ``user_loader`` is called with ``(subject,
194
+ session)``.
172
195
 
173
196
  Returns:
174
197
  Callable[..., Coroutine[Any, Any, Any]]: An async FastAPI
@@ -181,20 +204,41 @@ def make_jwt_user_dependency(
181
204
  error_message=error_message,
182
205
  )
183
206
 
184
- async def _current_user(
185
- payload: dict[str, Any] | None = Depends(decode_bearer),
186
- ) -> Any:
187
- if payload is None:
188
- return None
189
- subject = payload.get(subject_claim)
190
- if subject is None:
191
- if soft:
207
+ if session_dependency is None:
208
+
209
+ async def _current_user_owns_session(
210
+ payload: dict[str, Any] | None = Depends(decode_bearer),
211
+ ) -> Any:
212
+ if payload is None:
192
213
  return None
193
- raise UnauthorizedException(message=error_message)
194
- return await user_loader(subject)
214
+ subject = payload.get(subject_claim)
215
+ if subject is None:
216
+ if soft:
217
+ return None
218
+ raise UnauthorizedException(message=error_message)
219
+ return await user_loader(subject)
220
+
221
+ dependency = _current_user_owns_session
222
+
223
+ else:
224
+
225
+ async def _current_user_shared_session(
226
+ payload: dict[str, Any] | None = Depends(decode_bearer),
227
+ session: Any = Depends(session_dependency),
228
+ ) -> Any:
229
+ if payload is None:
230
+ return None
231
+ subject = payload.get(subject_claim)
232
+ if subject is None:
233
+ if soft:
234
+ return None
235
+ raise UnauthorizedException(message=error_message)
236
+ return await user_loader(subject, session)
237
+
238
+ dependency = _current_user_shared_session
195
239
 
196
- _current_user.__doc__ = "Decode the bearer JWT and resolve the authenticated user."
197
- return _current_user
240
+ dependency.__doc__ = "Decode the bearer JWT and resolve the authenticated user."
241
+ return dependency
198
242
 
199
243
 
200
244
  def make_role_dependency(
@@ -528,11 +528,12 @@ class UserAuthService:
528
528
  self,
529
529
  *,
530
530
  soft: bool = False,
531
+ session_dependency: Callable[..., Any] | None = None,
531
532
  ) -> Callable[..., Coroutine[Any, Any, Any]]:
532
533
  """Build a FastAPI dependency that returns the authenticated user.
533
534
 
534
535
  Wraps :func:`tempest_fastapi_sdk.make_jwt_user_dependency` with
535
- this service's own :class:`JWTUtils` and :meth:`load_user`, so
536
+ this service's own :class:`JWTUtils` and :meth:`get_user`, so
536
537
  the bearer token is verified with the **same** secret the
537
538
  service signs with — there is no second ``JWTUtils`` to keep in
538
539
  sync. Mount it on any of your routes:
@@ -542,23 +543,49 @@ class UserAuthService:
542
543
  ... soft=True
543
544
  ... )
544
545
 
545
- Requires the service to have been built with ``db=`` (consumed
546
- lazily by :meth:`load_user` on the first authenticated request).
546
+ The authenticated user is loaded on the **request-scoped**
547
+ session (``self.db.session_dependency`` by default), so it is
548
+ attached to the same session the request's repositories use and
549
+ can be mutated / refreshed without an
550
+ ``InvalidRequestError: Instance is not persistent within this
551
+ Session``. If your repositories depend on a different session
552
+ callable (e.g. a project-local ``get_session`` wrapper), pass it
553
+ as ``session_dependency`` so both resolve to the *same* request
554
+ session — FastAPI caches a sub-dependency by its callable, so a
555
+ distinct wrapper would open a second session and detach the user.
556
+
557
+ Requires the service to have been built with ``db=``.
547
558
 
548
559
  Args:
549
560
  soft (bool): When ``True``, the dependency returns ``None``
550
561
  instead of raising on a missing / invalid token — for
551
562
  endpoints that work both authenticated and anonymous.
563
+ session_dependency (Callable[..., Any] | None): The
564
+ request-scoped session provider to share with
565
+ repositories. Defaults to ``self.db.session_dependency``.
552
566
 
553
567
  Returns:
554
568
  Callable[..., Coroutine[Any, Any, Any]]: An async FastAPI
555
569
  dependency yielding the user (or ``None`` in soft mode).
570
+
571
+ Raises:
572
+ RuntimeError: When the service was created without ``db=``.
556
573
  """
574
+ if self.db is None:
575
+ raise RuntimeError(
576
+ "UserAuthService was created without `db=`; pass an "
577
+ "AsyncDatabaseManager to use current_user_dependency."
578
+ )
557
579
  from tempest_fastapi_sdk.api.dependencies.auth import (
558
580
  make_jwt_user_dependency,
559
581
  )
560
582
 
561
- return make_jwt_user_dependency(self.jwt, self.load_user, soft=soft)
583
+ return make_jwt_user_dependency(
584
+ self.jwt,
585
+ self.get_user,
586
+ soft=soft,
587
+ session_dependency=session_dependency or self.db.session_dependency,
588
+ )
562
589
 
563
590
  # ------------------------------------------------------------------
564
591
  # Authorization guards (imperative, on an already-loaded user)
@@ -9,7 +9,16 @@ from datetime import date, datetime
9
9
  from typing import Any, Generic, List, TypeVar, cast
10
10
  from uuid import UUID
11
11
 
12
- from sqlalchemy import CursorResult, Select, delete, func, insert, select, update
12
+ from sqlalchemy import (
13
+ CursorResult,
14
+ Select,
15
+ delete,
16
+ func,
17
+ insert,
18
+ inspect,
19
+ select,
20
+ update,
21
+ )
13
22
  from sqlalchemy.exc import IntegrityError
14
23
  from sqlalchemy.ext.asyncio import AsyncSession
15
24
 
@@ -337,14 +346,23 @@ class BaseRepository(Generic[ModelType]):
337
346
  ``if isinstance(x, UUID): ... else: ...`` boilerplate services
338
347
  reimplement whenever a method takes ``UUID | Model``.
339
348
 
349
+ When given a **detached** instance (one whose session has been
350
+ closed — e.g. a user loaded by an auth dependency on its own
351
+ short-lived session) it is re-attached to this repository's
352
+ session via :meth:`AsyncSession.merge`. Returning it as-is would
353
+ later raise ``InvalidRequestError: Instance is not persistent
354
+ within this Session`` on the first ``commit`` / ``refresh``.
355
+ ``merge`` issues a ``SELECT`` only when the row is not already in
356
+ this session's identity map.
357
+
340
358
  Args:
341
359
  ref (UUID | ModelType): The primary key to look up, or an
342
- already-loaded instance to return as-is.
360
+ already-loaded instance to attach and return.
343
361
  for_update (bool): Whether to acquire a row-level lock when
344
362
  ``ref`` is a ``UUID`` (ignored when an instance is given).
345
363
 
346
364
  Returns:
347
- ModelType: The resolved instance.
365
+ ModelType: The resolved instance, attached to this session.
348
366
 
349
367
  Raises:
350
368
  AppException: ``self.not_found_exception`` when ``ref`` is a
@@ -352,6 +370,8 @@ class BaseRepository(Generic[ModelType]):
352
370
  """
353
371
  if isinstance(ref, UUID):
354
372
  return await self.get_by_id(ref, for_update=for_update)
373
+ if inspect(ref).detached:
374
+ return await self.session.merge(ref)
355
375
  return ref
356
376
 
357
377
  async def exists(self, filters: dict[str, Any]) -> bool:
@@ -94,6 +94,34 @@ class BasePaginationFilterSchema(BaseSchema):
94
94
  exclude=["page", "page_size", "order_by", "ascending"],
95
95
  )
96
96
 
97
+ def get_pagination_conditions(self) -> dict[str, Any]:
98
+ """Return only the pagination and sort keyword arguments.
99
+
100
+ Complements :meth:`get_conditions`: where that method strips the
101
+ pagination keys to expose the domain filters, this one keeps only
102
+ the pagination keys (``page``, ``page_size``, ``order_by``,
103
+ ``ascending``). Together they let a service forward a filter
104
+ schema to :meth:`BaseRepository.paginate` without manually
105
+ unpacking the model, which would also leak domain filters such as
106
+ ``is_active`` into kwargs the repository does not accept:
107
+
108
+ .. code-block:: python
109
+
110
+ data = await repo.paginate(
111
+ filters=f.get_conditions(),
112
+ **f.get_pagination_conditions(),
113
+ )
114
+
115
+ Returns:
116
+ dict[str, Any]: The pagination/sort keyword arguments.
117
+ """
118
+ return {
119
+ "page": self.page,
120
+ "page_size": self.page_size,
121
+ "order_by": self.order_by,
122
+ "ascending": self.ascending,
123
+ }
124
+
97
125
 
98
126
  T = TypeVar("T", bound=BaseSchema)
99
127
 
@@ -210,6 +238,34 @@ class CursorPaginationFilterSchema(BaseSchema):
210
238
  exclude=["cursor", "limit", "order_by", "ascending"],
211
239
  )
212
240
 
241
+ def get_pagination_conditions(self) -> dict[str, Any]:
242
+ """Return only the cursor pagination and sort keyword arguments.
243
+
244
+ Complements :meth:`get_conditions`: where that method strips the
245
+ pagination keys to expose the domain filters, this one keeps only
246
+ the pagination keys (``cursor``, ``limit``, ``order_by``,
247
+ ``ascending``). Together they let a service forward a filter
248
+ schema to :meth:`BaseRepository.cursor_paginate` without manually
249
+ unpacking the model, which would also leak domain filters into
250
+ kwargs the repository does not accept:
251
+
252
+ .. code-block:: python
253
+
254
+ data = await repo.cursor_paginate(
255
+ filters=f.get_conditions(),
256
+ **f.get_pagination_conditions(),
257
+ )
258
+
259
+ Returns:
260
+ dict[str, Any]: The cursor pagination/sort keyword arguments.
261
+ """
262
+ return {
263
+ "cursor": self.cursor,
264
+ "limit": self.limit,
265
+ "order_by": self.order_by,
266
+ "ascending": self.ascending,
267
+ }
268
+
213
269
 
214
270
  class CursorPaginationSchema(BaseSchema, Generic[T]):
215
271
  """Generic envelope returned by cursor-paginated endpoints.
@@ -9,7 +9,7 @@ from typing import Any
9
9
  import pytest
10
10
  from fastapi import Depends, FastAPI
11
11
  from httpx import ASGITransport, AsyncClient
12
- from sqlalchemy import select
12
+ from sqlalchemy import inspect, select
13
13
  from sqlalchemy.ext.asyncio import (
14
14
  AsyncSession,
15
15
  async_sessionmaker,
@@ -1507,6 +1507,68 @@ class TestCurrentUserResolution:
1507
1507
  finally:
1508
1508
  await db.disconnect()
1509
1509
 
1510
+ async def test_current_user_attached_to_request_session(self) -> None:
1511
+ """The authenticated user is attached to the request-scoped session.
1512
+
1513
+ Regression for ``InvalidRequestError: Instance is not persistent
1514
+ within this Session``: loading the user on a private auth session
1515
+ yielded a *detached* instance, so mutating it on the request's
1516
+ repository session never persisted (and ``refresh`` raised). The
1517
+ dependency now shares ``db.session_dependency`` with the route, so
1518
+ the user is live and a mutation commits.
1519
+ """
1520
+ db, service = await _db_service()
1521
+ try:
1522
+ async with db.get_session_context() as s:
1523
+ user, _ = await service.signup(
1524
+ s,
1525
+ email="attached@a.com",
1526
+ password="strong-pass-12-chars",
1527
+ )
1528
+ user.is_active = True
1529
+ await s.commit()
1530
+ await s.refresh(user)
1531
+ user_id = user.id
1532
+ access, _ = service.issue_jwt_pair(user)
1533
+
1534
+ get_current_user = service.current_user_dependency()
1535
+ app = FastAPI()
1536
+
1537
+ @app.post("/deactivate")
1538
+ async def deactivate(
1539
+ current: Any = Depends(get_current_user),
1540
+ session: AsyncSession = Depends(db.session_dependency),
1541
+ ) -> dict[str, bool]:
1542
+ # The user is attached to this very request session: its
1543
+ # underlying sync Session is the dependency's shared one.
1544
+ same_session = inspect(current).session is session.sync_session
1545
+ current.is_active = False
1546
+ await session.commit()
1547
+ await session.refresh(current) # would raise if detached
1548
+ return {"same_session": same_session}
1549
+
1550
+ async with AsyncClient(
1551
+ transport=ASGITransport(app=app), base_url="http://t"
1552
+ ) as client:
1553
+ resp = await client.post(
1554
+ "/deactivate", headers={"Authorization": f"Bearer {access}"}
1555
+ )
1556
+ assert resp.status_code == 200
1557
+ assert resp.json() == {"same_session": True}
1558
+
1559
+ # The mutation actually hit the database.
1560
+ async with db.get_session_context() as verify:
1561
+ reloaded = await service.get_user(user_id, verify)
1562
+ assert reloaded.is_active is False
1563
+ finally:
1564
+ await db.disconnect()
1565
+
1566
+ async def test_current_user_without_db_raises(self) -> None:
1567
+ """``current_user_dependency`` needs ``db=`` to share its session."""
1568
+ service = _service() # built without db=
1569
+ with pytest.raises(RuntimeError):
1570
+ service.current_user_dependency()
1571
+
1510
1572
  async def test_current_user_dependency_soft_returns_none(self) -> None:
1511
1573
  db, service = await _db_service()
1512
1574
  try: