tempest-fastapi-sdk 0.90.0__tar.gz → 0.92.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 (509) hide show
  1. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/CHANGELOG.md +106 -0
  2. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/CLAUDE.md +26 -11
  3. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/PKG-INFO +10 -7
  4. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/README.md +9 -6
  5. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/migration.en.md +30 -0
  6. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/migration.md +30 -0
  7. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/auth-flow.en.md +49 -0
  8. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/auth-flow.md +49 -0
  9. tempest_fastapi_sdk-0.92.0/docs/recipes/sse.en.md +390 -0
  10. tempest_fastapi_sdk-0.92.0/docs/recipes/sse.md +390 -0
  11. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/pyproject.toml +1 -1
  12. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/__init__.py +15 -1
  13. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/dependencies/auth.py +38 -7
  14. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/__init__.py +22 -0
  15. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/locale.py +24 -4
  16. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/router.py +240 -0
  17. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/schemas.py +223 -0
  18. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/service.py +423 -1
  19. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_change.html +20 -0
  20. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_change_error.html +27 -0
  21. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_change_success.html +23 -0
  22. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_changed_notice.html +10 -0
  23. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_verification.html +19 -0
  24. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_verification_error.html +26 -0
  25. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_verification_success.html +23 -0
  26. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_change.html +20 -0
  27. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_error.html +27 -0
  28. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_success.html +23 -0
  29. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_changed_notice.html +10 -0
  30. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification.html +19 -0
  31. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_error.html +26 -0
  32. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_success.html +23 -0
  33. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_token_model.py +18 -2
  34. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/settings/mixins.py +138 -0
  35. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/sse/__init__.py +23 -0
  36. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sse/broker.py +53 -2
  37. tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/sse/event_stream.py +368 -0
  38. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_jwt_dependency.py +75 -0
  39. tempest_fastapi_sdk-0.92.0/tests/auth/test_email_change.py +472 -0
  40. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sse/test_broker.py +35 -0
  41. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sse/test_event_stream.py +98 -0
  42. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/uv.lock +1 -1
  43. tempest_fastapi_sdk-0.90.0/docs/recipes/sse.en.md +0 -226
  44. tempest_fastapi_sdk-0.90.0/docs/recipes/sse.md +0 -226
  45. tempest_fastapi_sdk-0.90.0/tempest_fastapi_sdk/sse/__init__.py +0 -15
  46. tempest_fastapi_sdk-0.90.0/tempest_fastapi_sdk/sse/event_stream.py +0 -205
  47. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.github/workflows/ci.yml +0 -0
  48. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.github/workflows/docs.yml +0 -0
  49. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.github/workflows/release-pypi.yml +0 -0
  50. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.gitignore +0 -0
  51. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.python-version +0 -0
  52. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/Makefile +0 -0
  53. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/architecture.en.md +0 -0
  54. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/architecture.md +0 -0
  55. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/changelog.en.md +0 -0
  56. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/changelog.md +0 -0
  57. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/contributing.en.md +0 -0
  58. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/contributing.md +0 -0
  59. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/index.en.md +0 -0
  60. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/index.md +0 -0
  61. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/installation.en.md +0 -0
  62. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/installation.md +0 -0
  63. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/index.en.md +0 -0
  64. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/index.md +0 -0
  65. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/api.en.md +0 -0
  66. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/api.md +0 -0
  67. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/business-rules.en.md +0 -0
  68. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/business-rules.md +0 -0
  69. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/domain.en.md +0 -0
  70. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/domain.md +0 -0
  71. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/flows.en.md +0 -0
  72. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/flows.md +0 -0
  73. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/index.en.md +0 -0
  74. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/index.md +0 -0
  75. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/admin.en.md +0 -0
  76. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/admin.md +0 -0
  77. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/audit-trail.en.md +0 -0
  78. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/audit-trail.md +0 -0
  79. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/br-helpers.en.md +0 -0
  80. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/br-helpers.md +0 -0
  81. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cache.en.md +0 -0
  82. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cache.md +0 -0
  83. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cli.en.md +0 -0
  84. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cli.md +0 -0
  85. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/database.en.md +0 -0
  86. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/database.md +0 -0
  87. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/deploy-safety.en.md +0 -0
  88. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/deploy-safety.md +0 -0
  89. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/downloads.en.md +0 -0
  90. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/downloads.md +0 -0
  91. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/email.en.md +0 -0
  92. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/email.md +0 -0
  93. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/feature-flags.en.md +0 -0
  94. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/feature-flags.md +0 -0
  95. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/fields.en.md +0 -0
  96. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/fields.md +0 -0
  97. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/file-store.en.md +0 -0
  98. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/file-store.md +0 -0
  99. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http-client.en.md +0 -0
  100. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http-client.md +0 -0
  101. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http.en.md +0 -0
  102. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http.md +0 -0
  103. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/idempotency.en.md +0 -0
  104. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/idempotency.md +0 -0
  105. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/index.en.md +0 -0
  106. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/index.md +0 -0
  107. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/logging.en.md +0 -0
  108. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/logging.md +0 -0
  109. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/metrics.en.md +0 -0
  110. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/metrics.md +0 -0
  111. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/mfa.en.md +0 -0
  112. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/mfa.md +0 -0
  113. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/multi-tenant.en.md +0 -0
  114. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/multi-tenant.md +0 -0
  115. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/observability.en.md +0 -0
  116. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/observability.md +0 -0
  117. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/offline-sync.en.md +0 -0
  118. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/offline-sync.md +0 -0
  119. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/outbox.en.md +0 -0
  120. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/outbox.md +0 -0
  121. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/queue-tasks.en.md +0 -0
  122. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/queue-tasks.md +0 -0
  123. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/realtime.en.md +0 -0
  124. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/realtime.md +0 -0
  125. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/refresh-tokens.en.md +0 -0
  126. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/refresh-tokens.md +0 -0
  127. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/security.en.md +0 -0
  128. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/security.md +0 -0
  129. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/sessions.en.md +0 -0
  130. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/sessions.md +0 -0
  131. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/storage.en.md +0 -0
  132. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/storage.md +0 -0
  133. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/stored-files.en.md +0 -0
  134. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/stored-files.md +0 -0
  135. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/testing.en.md +0 -0
  136. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/testing.md +0 -0
  137. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/typing.en.md +0 -0
  138. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/typing.md +0 -0
  139. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/uploads.en.md +0 -0
  140. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/uploads.md +0 -0
  141. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/utilities.en.md +0 -0
  142. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/utilities.md +0 -0
  143. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/vision.en.md +0 -0
  144. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/vision.md +0 -0
  145. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/webpush.en.md +0 -0
  146. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/webpush.md +0 -0
  147. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/websocket.en.md +0 -0
  148. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/websocket.md +0 -0
  149. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/reference.en.md +0 -0
  150. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/reference.md +0 -0
  151. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/roadmap.en.md +0 -0
  152. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/roadmap.md +0 -0
  153. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/ssr.en.md +0 -0
  154. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/ssr.md +0 -0
  155. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/tutorial.en.md +0 -0
  156. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/tutorial.md +0 -0
  157. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/mkdocs.yml +0 -0
  158. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/mkdocs_hooks/llmstxt.py +0 -0
  159. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/scripts/extract_recipe.py +0 -0
  160. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
  161. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/actions.py +0 -0
  162. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
  163. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/config.py +0 -0
  164. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/discovery.py +0 -0
  165. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
  166. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/router.py +0 -0
  167. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/session.py +0 -0
  168. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/site.py +0 -0
  169. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
  170. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
  171. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
  172. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
  173. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
  174. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
  175. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
  176. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
  177. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
  178. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/theme.py +0 -0
  179. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
  180. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
  181. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
  182. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
  183. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
  184. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
  185. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
  186. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
  187. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
  188. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
  189. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
  190. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
  191. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
  192. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
  193. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
  194. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
  195. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
  196. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
  197. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/server.py +0 -0
  198. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/static.py +0 -0
  199. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
  200. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
  201. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
  202. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
  203. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
  204. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
  205. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
  206. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
  207. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
  208. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
  209. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
  210. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
  211. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
  212. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
  213. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
  214. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
  215. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
  216. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
  217. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/token_delivery.py +0 -0
  218. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
  219. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
  220. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
  221. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
  222. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
  223. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/Dockerfile.tmpl +0 -0
  224. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
  225. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/dockerignore.tmpl +0 -0
  226. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
  227. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
  228. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
  229. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
  230. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
  231. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
  232. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
  233. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
  234. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
  235. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
  236. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
  237. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
  238. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
  239. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
  240. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
  241. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
  242. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
  243. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
  244. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
  245. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
  246. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
  247. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
  248. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
  249. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
  250. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
  251. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/config.py +0 -0
  252. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/db.py +0 -0
  253. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
  254. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
  255. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
  256. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/main.py +0 -0
  257. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/new.py +0 -0
  258. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
  259. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
  260. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/user.py +0 -0
  261. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
  262. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
  263. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
  264. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/context.py +0 -0
  265. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/enums.py +0 -0
  266. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/logging.py +0 -0
  267. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/typed.py +0 -0
  268. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
  269. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
  270. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
  271. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
  272. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/audit.py +0 -0
  273. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/backup.py +0 -0
  274. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/connection.py +0 -0
  275. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
  276. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
  277. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/model.py +0 -0
  278. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
  279. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/repository.py +0 -0
  280. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
  281. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
  282. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
  283. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
  284. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_refresh_token_model.py +0 -0
  285. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/webpush_subscription_model.py +0 -0
  286. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
  287. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
  288. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
  289. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
  290. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
  291. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
  292. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
  293. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
  294. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
  295. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
  296. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
  297. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
  298. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
  299. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
  300. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/service.py +0 -0
  301. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/py.typed +0 -0
  302. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
  303. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
  304. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
  305. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
  306. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
  307. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
  308. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
  309. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
  310. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
  311. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/services/base.py +0 -0
  312. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/services/file_mixin.py +0 -0
  313. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
  314. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
  315. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
  316. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
  317. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
  318. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
  319. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
  320. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
  321. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/settings/base.py +0 -0
  322. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/__init__.py +0 -0
  323. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/_static/htmx.min.js +0 -0
  324. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/assets.py +0 -0
  325. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/page.py +0 -0
  326. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/response.py +0 -0
  327. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
  328. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
  329. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
  330. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
  331. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
  332. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
  333. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/testing/database.py +0 -0
  334. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
  335. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
  336. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
  337. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
  338. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
  339. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/download.py +0 -0
  340. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/email.py +0 -0
  341. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/fields.py +0 -0
  342. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/file_store.py +0 -0
  343. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
  344. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
  345. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
  346. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/log.py +0 -0
  347. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
  348. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
  349. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/password.py +0 -0
  350. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
  351. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
  352. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
  353. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
  354. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
  355. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/vision/__init__.py +0 -0
  356. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/vision/mapping.py +0 -0
  357. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/vision/schemas.py +0 -0
  358. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
  359. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
  360. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/router.py +0 -0
  361. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
  362. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/service.py +0 -0
  363. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
  364. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
  365. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
  366. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
  367. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/__init__.py +0 -0
  368. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/__init__.py +0 -0
  369. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_actions.py +0 -0
  370. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_auth.py +0 -0
  371. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_discovery.py +0 -0
  372. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_forms.py +0 -0
  373. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_logs_nav.py +0 -0
  374. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_mfa.py +0 -0
  375. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_rich_filters.py +0 -0
  376. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_router.py +0 -0
  377. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_site.py +0 -0
  378. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_theme.py +0 -0
  379. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_upload_field.py +0 -0
  380. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_user_model.py +0 -0
  381. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/__init__.py +0 -0
  382. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_body_size.py +0 -0
  383. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_cookies.py +0 -0
  384. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_cors.py +0 -0
  385. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_csrf.py +0 -0
  386. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_dependencies_auth.py +0 -0
  387. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_graceful.py +0 -0
  388. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_handlers.py +0 -0
  389. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_health_router.py +0 -0
  390. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_idempotency.py +0 -0
  391. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_logs_router.py +0 -0
  392. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_oauth.py +0 -0
  393. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_prometheus.py +0 -0
  394. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_rate_limit.py +0 -0
  395. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_rate_limit_extras.py +0 -0
  396. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_request_id_middleware.py +0 -0
  397. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_role_dependency.py +0 -0
  398. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_server.py +0 -0
  399. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_static.py +0 -0
  400. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_tool_spec.py +0 -0
  401. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_tracing.py +0 -0
  402. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_webhooks.py +0 -0
  403. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_webhooks_rsa.py +0 -0
  404. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/__init__.py +0 -0
  405. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_cookie_delivery.py +0 -0
  406. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_guards.py +0 -0
  407. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_locale.py +0 -0
  408. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_mfa.py +0 -0
  409. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_refresh.py +0 -0
  410. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_refresh_db.py +0 -0
  411. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_service.py +0 -0
  412. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/__init__.py +0 -0
  413. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/test_decorator.py +0 -0
  414. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/test_invalidation.py +0 -0
  415. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/test_redis_manager.py +0 -0
  416. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/__init__.py +0 -0
  417. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_config.py +0 -0
  418. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_db.py +0 -0
  419. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_db_seed.py +0 -0
  420. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_docker_compose.py +0 -0
  421. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_generate.py +0 -0
  422. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_lint_strictness.py +0 -0
  423. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_main.py +0 -0
  424. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_secrets.py +0 -0
  425. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_user.py +0 -0
  426. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/conftest.py +0 -0
  427. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/controllers/__init__.py +0 -0
  428. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/controllers/test_base.py +0 -0
  429. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/__init__.py +0 -0
  430. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_context.py +0 -0
  431. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_enums.py +0 -0
  432. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_logging.py +0 -0
  433. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_typed.py +0 -0
  434. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/__init__.py +0 -0
  435. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_alembic_hooks.py +0 -0
  436. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_audit.py +0 -0
  437. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_backup.py +0 -0
  438. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_bulk_ops.py +0 -0
  439. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_connection.py +0 -0
  440. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_migrations.py +0 -0
  441. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_mixins.py +0 -0
  442. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_model.py +0 -0
  443. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_outbox.py +0 -0
  444. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_repository.py +0 -0
  445. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_safe_upgrade.py +0 -0
  446. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_slow_query.py +0 -0
  447. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_tenant.py +0 -0
  448. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/exceptions/__init__.py +0 -0
  449. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/exceptions/test_exceptions.py +0 -0
  450. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/exceptions/test_i18n.py +0 -0
  451. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/flags/__init__.py +0 -0
  452. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/flags/test_flags.py +0 -0
  453. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/queue/__init__.py +0 -0
  454. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/queue/test_manager.py +0 -0
  455. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/__init__.py +0 -0
  456. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_base.py +0 -0
  457. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_cursor_pagination.py +0 -0
  458. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_link_headers.py +0 -0
  459. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_pagination.py +0 -0
  460. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_response.py +0 -0
  461. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/services/__init__.py +0 -0
  462. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/services/test_base.py +0 -0
  463. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/services/test_file_mixin.py +0 -0
  464. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sessions/__init__.py +0 -0
  465. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sessions/test_sessions.py +0 -0
  466. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/settings/__init__.py +0 -0
  467. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/settings/test_base.py +0 -0
  468. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/settings/test_mixins.py +0 -0
  469. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sse/__init__.py +0 -0
  470. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/__init__.py +0 -0
  471. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/test_integration.py +0 -0
  472. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/test_page.py +0 -0
  473. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/test_response.py +0 -0
  474. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/storage/__init__.py +0 -0
  475. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/storage/test_minio_client.py +0 -0
  476. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/tasks/__init__.py +0 -0
  477. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/tasks/test_manager.py +0 -0
  478. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/tasks/test_scheduler.py +0 -0
  479. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/testing/__init__.py +0 -0
  480. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/testing/test_database.py +0 -0
  481. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/__init__.py +0 -0
  482. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_client_ip.py +0 -0
  483. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_datetime.py +0 -0
  484. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_dict.py +0 -0
  485. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_download.py +0 -0
  486. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_email.py +0 -0
  487. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_fields.py +0 -0
  488. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_file_store.py +0 -0
  489. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_http_client.py +0 -0
  490. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_jwt.py +0 -0
  491. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_lazy_extras.py +0 -0
  492. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_locations.py +0 -0
  493. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_log.py +0 -0
  494. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_metrics.py +0 -0
  495. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_opaque_token.py +0 -0
  496. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_password.py +0 -0
  497. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_regex.py +0 -0
  498. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_storage_backends.py +0 -0
  499. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_throttle.py +0 -0
  500. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_upload.py +0 -0
  501. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/vision/__init__.py +0 -0
  502. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/vision/test_vision.py +0 -0
  503. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/__init__.py +0 -0
  504. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_dispatcher.py +0 -0
  505. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_router.py +0 -0
  506. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_schemas.py +0 -0
  507. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_service.py +0 -0
  508. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/websockets/__init__.py +0 -0
  509. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/websockets/test_hub_and_router.py +0 -0
@@ -5,6 +5,112 @@ 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.92.0] — 2026-07-05
9
+
10
+ ### Added
11
+
12
+ - **Email change / re-verification / recovery flow** on `UserAuthService`
13
+ + `make_auth_router`, mirroring the password reset/change surface:
14
+ - **Change email (authenticated)** — `request_email_change` (verifies
15
+ the current password, stages the new address, emails a confirmation
16
+ link to the NEW address) + `confirm_email_change` (consumes the
17
+ token, flips the email, and — when `AUTH_EMAIL_CHANGE_NOTIFY_OLD`
18
+ is on — sends a security notice to the OLD address). Routes:
19
+ `POST /auth/email-change/request` (202) and
20
+ `POST /auth/email-change/confirm`.
21
+ - **Re-verify current email** — `request_email_verification` /
22
+ `confirm_email_verification` (resend a verification link to the
23
+ current address; confirming marks the account active). Routes:
24
+ `POST /auth/email-verify/request` (202) and
25
+ `POST /auth/email-verify/confirm`.
26
+ - **Recovery (lost mailbox access)** — `request_email_recovery`, an
27
+ **unauthenticated** entry point that proves identity with the
28
+ account password **plus a valid MFA code when TOTP is enrolled**,
29
+ then emails the confirmation link to the new address. Always returns
30
+ a generic `202` for soft failures (unknown email, wrong password,
31
+ bad/missing MFA code) so it can't enumerate accounts. Route
32
+ `POST /auth/email-recovery/request` is **opt-in** via
33
+ `AUTH_EMAIL_RECOVERY_ENABLED` (off by default).
34
+ - **Old-email security notice** on a confirmed change, toggled by
35
+ `AUTH_EMAIL_CHANGE_NOTIFY_OLD` (default `True`).
36
+ - **Backend HTML pages** (when `AUTH_BACKEND_LINKS=True`):
37
+ `GET /auth/email-change/{token}` and `GET /auth/email-verify/{token}`
38
+ render self-contained success/error pages — no frontend needed.
39
+ - New schemas exported from the package root:
40
+ `EmailChangeRequestSchema`, `EmailChangeConfirmSchema`,
41
+ `EmailRecoveryRequestSchema`, `EmailChangeResponseSchema`,
42
+ `EmailChangeToken`, `EmailVerificationToken`.
43
+ - New `UserTokenPurpose.EMAIL_CHANGE`; the existing
44
+ `EMAIL_VERIFICATION` purpose now backs the re-verify flow.
45
+ - 14 bundled bilingual templates (PT-BR + EN-US): `email_change.html`,
46
+ `email_verification.html`, `email_changed_notice.html`, plus
47
+ `email_change_success/error.html` and
48
+ `email_verification_success/error.html`.
49
+ - Localized subjects/bodies for the three new emails.
50
+ - New settings: `AUTH_EMAIL_CHANGE_TTL_SECONDS`,
51
+ `AUTH_EMAIL_VERIFICATION_TTL_SECONDS`,
52
+ `AUTH_EMAIL_CHANGE_URL_TEMPLATE`,
53
+ `AUTH_EMAIL_VERIFICATION_URL_TEMPLATE`, `AUTH_EMAIL_CHANGE_TEMPLATE`,
54
+ `AUTH_EMAIL_VERIFICATION_TEMPLATE`,
55
+ `AUTH_EMAIL_CHANGED_NOTICE_TEMPLATE`, `AUTH_EMAIL_CHANGE_NOTIFY_OLD`,
56
+ `AUTH_EMAIL_RECOVERY_ENABLED`, `AUTH_EMAIL_CHANGE_SUCCESS_TEMPLATE`,
57
+ `AUTH_EMAIL_CHANGE_ERROR_TEMPLATE`,
58
+ `AUTH_EMAIL_VERIFICATION_SUCCESS_TEMPLATE`,
59
+ `AUTH_EMAIL_VERIFICATION_ERROR_TEMPLATE`.
60
+
61
+ ### Changed
62
+
63
+ - **`BaseUserTokenModel` gains a nullable `payload` column**
64
+ (`VARCHAR(320)`) carrying flow context — the pending new email for an
65
+ `EMAIL_CHANGE` token. **Requires a migration** in consuming projects
66
+ (additive nullable column, safe). See the migration guide.
67
+
68
+ ## [0.91.0] — 2026-07-05
69
+
70
+ ### Added
71
+
72
+ - **SSE backpressure — bounded queue + overflow policy.**
73
+ `EventStream` (and `SSEBroker`-created streams) now cap the buffered
74
+ events at `max_queue` (default `1000`) instead of growing without
75
+ limit when a client stalls. When the buffer fills, `overflow` decides
76
+ what gives:
77
+ - `"drop_oldest"` (default) — evict the stalest event, keep the
78
+ freshest data.
79
+ - `"drop_newest"` — discard the incoming event, keep the backlog.
80
+ - `"block"` — apply real backpressure (the producer waits for a slot).
81
+ `EventStream.dropped_events` counts events lost to overflow for
82
+ metrics / logs. `max_queue=0` restores the pre-0.91 unbounded
83
+ behavior. The `close()` sentinel is never dropped or blocked, so a
84
+ stream can always terminate. `SSEBroker(max_queue=..., overflow=...)`
85
+ applies the same policy to every stream it opens.
86
+ - **SSE lifecycle helpers — no more hand-rolled `try/finally`.**
87
+ - `sse_response(..., on_disconnect=...)` runs a cleanup callback
88
+ (awaited if a coroutine) when the client disconnects or the stream
89
+ ends — the one place guaranteed to fire — so a bound producer task
90
+ is cancelled or a channel unregistered without boilerplate.
91
+ - `EventStream.response(*, on_disconnect=..., status_code=...,
92
+ headers=...)` wraps `stream()` in an SSE response in one call.
93
+ - `SSEBroker.response(channel, ...)` bundles the whole per-connection
94
+ lifecycle: `register` + `sse_response` + `unregister`-on-disconnect.
95
+ This removes the leak-prone manual wrapper the recipe used to need.
96
+ - **JWT via query string for cookieless clients.**
97
+ `make_bearer_token_dependency` and `make_jwt_user_dependency` gained a
98
+ `query_param` argument (e.g. `query_param="access_token"`). Token
99
+ lookup order becomes header → cookie → query string. This unblocks
100
+ browser `EventSource` (SSE), whose constructor accepts neither headers
101
+ nor a body. Documented with a security warning: use short-lived access
102
+ tokens only, over TLS, and scrub the value from access logs. Prefer a
103
+ session cookie (`withCredentials`) whenever the client shares the
104
+ API's origin.
105
+ - **`OverflowPolicy`** is exported from `tempest_fastapi_sdk.sse` and the
106
+ package root.
107
+
108
+ ### Fixed
109
+
110
+ - `tempest_fastapi_sdk/sse/__init__.py` re-exports now use the explicit
111
+ `X as X` alias form required by the repo's re-export convention (was a
112
+ structural defect flagged by strict type-checkers).
113
+
8
114
  ## [0.90.0] — 2026-07-04
9
115
 
10
116
  ### Added
@@ -55,16 +55,26 @@ without the docs being green.
55
55
 
56
56
  The SDK currently covers (Sep 2025+, post-v0.31.x):
57
57
 
58
- - **Auth** — JWT/bearer/role/permission/X-Token deps, full
58
+ - **Auth** — JWT/bearer/role/permission/X-Token deps (JWT deps
59
+ read the token from header → cookie → query string via
60
+ `query_param=`, for cookieless `EventSource`/SSE clients), full
59
61
  bundled flow (`UserAuthService` + `make_auth_router` covering
60
62
  signup/activate/login/password-reset), `BaseUserModel` +
61
- `BaseUserTokenModel`, OAuth2/OIDC providers
62
- (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`),
63
- CSRF middleware + `make_csrf_token_dependency`, opt-in
64
- DB-backed opaque refresh tokens (`BaseUserRefreshTokenModel`,
65
- `make_user_refresh_token_model`, `refresh_token_model=` on
66
- `UserAuthService`) with rotation, family-wide reuse detection
67
- and `POST /auth/logout` (`LogoutSchema`).
63
+ `BaseUserTokenModel` (nullable `payload` column carrying flow
64
+ context), email change/re-verify/recovery
65
+ (`request_email_change`/`confirm_email_change`,
66
+ `request_email_verification`/`confirm_email_verification`,
67
+ `request_email_recovery` — password + MFA-if-enrolled, opt-in
68
+ `AUTH_EMAIL_RECOVERY_ENABLED`; old-email security notice via
69
+ `AUTH_EMAIL_CHANGE_NOTIFY_OLD`; `EMAIL_CHANGE` token purpose;
70
+ JSON + backend HTML pages + bilingual templates), OAuth2/OIDC
71
+ providers (`GoogleOAuthClient`, `GitHubOAuthClient`,
72
+ `OIDCProvider`), CSRF middleware + `make_csrf_token_dependency`,
73
+ opt-in DB-backed opaque refresh tokens
74
+ (`BaseUserRefreshTokenModel`, `make_user_refresh_token_model`,
75
+ `refresh_token_model=` on `UserAuthService`) with rotation,
76
+ family-wide reuse detection and `POST /auth/logout`
77
+ (`LogoutSchema`).
68
78
  - **DB** — `AsyncDatabaseManager`, `BaseRepository[T]` with
69
79
  bulk ops (`bulk_create_values`, `bulk_upsert`, `bulk_update`,
70
80
  `add_all`, etc.), `AlembicHelper`, `BaseModel`, audit /
@@ -88,9 +98,14 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
88
98
  - **Pagination** — offset + cursor.
89
99
  - **Settings mixins** — every `*Settings` carries
90
100
  `title`/`description`/`examples` on every field.
91
- - **SSE** — `EventStream`, `ServerSentEvent`, `sse_response`, and
92
- `SSEBroker` (per-channel fan-out; in-memory single-process, or
93
- multi-worker via an injected Redis pub/sub bridge — same call site).
101
+ - **SSE** — `EventStream` (bounded queue + `overflow` backpressure —
102
+ `drop_oldest`/`drop_newest`/`block`, `dropped_events` counter,
103
+ `max_queue=0` to disable), `ServerSentEvent`, `sse_response`
104
+ (`on_disconnect=` cleanup), `EventStream.response`, and `SSEBroker`
105
+ (per-channel fan-out; `SSEBroker.response(channel)` bundles
106
+ register + response + unregister-on-disconnect; in-memory
107
+ single-process, or multi-worker via an injected Redis pub/sub bridge
108
+ — same call site).
94
109
  - **Throttle** — `AttemptThrottle` (any `ThrottleBackend`, e.g.
95
110
  `redis.asyncio.Redis`; no in-memory backend bundled).
96
111
  - **Base CRUD layers** — `BaseService[Repo, Resp, UpdateT]` and
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tempest-fastapi-sdk
3
- Version: 0.90.0
3
+ Version: 0.92.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
@@ -200,7 +200,7 @@ Via `pyproject.toml`:
200
200
 
201
201
  ```toml
202
202
  dependencies = [
203
- "tempest-fastapi-sdk>=0.90.0",
203
+ "tempest-fastapi-sdk>=0.91.0",
204
204
  ]
205
205
  ```
206
206
 
@@ -253,12 +253,12 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
253
253
  | `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException`, i18n (`MessageCatalog`, `default_message_catalog`, `parse_accept_language`, `DEFAULT_LOCALE`) |
254
254
  | `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
255
255
  | `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` (+ `RateLimitStore`/`MemoryRateLimitStore`/`RedisRateLimitStore`/`RateLimitResult` and `key_by_ip`/`key_by_jwt_subject`/`key_by_jwt_claim`/`key_by_header`), `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `GracefulShutdownMiddleware`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
256
- | `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + TOTP 2FA out of the box |
256
+ | `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, email change/verify/recovery (`EmailChangeRequestSchema` / `EmailChangeConfirmSchema` / `EmailRecoveryRequestSchema` / `EmailChangeToken` / `EmailVerificationToken`, old-email security notice, opt-in `AUTH_EMAIL_RECOVERY_ENABLED`), MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + email change/recovery + TOTP 2FA out of the box |
257
257
  | `tempest_fastapi_sdk.controllers` | `BaseController` |
258
258
  | `tempest_fastapi_sdk.services` | `BaseService` |
259
259
  | `tempest_fastapi_sdk.core` | `configure_logging`, `JSONFormatter`, `get_request_id`/`set_request_id`/`clear_request_id`, `request_id_ctx`, `BaseStrEnum`, `BaseIntEnum`, `strict_types`/`typed`/`require_annotations` |
260
260
  | `tempest_fastapi_sdk.admin` *(extra: `[admin]`)* | `AdminSite`, `AdminModel`, `make_admin_router`, `AdminAuthBackend`, `UserModelAuthBackend`, `AdminAuthError` |
261
- | `tempest_fastapi_sdk.sse` | `EventStream`, `SSEBroker` (multi-worker fan-out via Redis), `ServerSentEvent`, `sse_response` |
261
+ | `tempest_fastapi_sdk.sse` | `EventStream` (bounded queue + `overflow` backpressure), `SSEBroker` (multi-worker fan-out via Redis, `.response()` lifecycle helper), `ServerSentEvent`, `sse_response` (`on_disconnect=` cleanup) |
262
262
  | `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
263
263
  | `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
264
264
  | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `make_web_push_router`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
@@ -2445,7 +2445,7 @@ import asyncio
2445
2445
 
2446
2446
  from fastapi import APIRouter
2447
2447
 
2448
- from tempest_fastapi_sdk import EventStream, sse_response
2448
+ from tempest_fastapi_sdk import EventStream
2449
2449
 
2450
2450
  router = APIRouter()
2451
2451
 
@@ -2460,8 +2460,9 @@ async def events() -> "StreamingResponse": # forward-declared by Starlette
2460
2460
  await asyncio.sleep(1)
2461
2461
  await stream.close()
2462
2462
 
2463
- asyncio.create_task(producer())
2464
- return sse_response(stream.stream())
2463
+ task = asyncio.create_task(producer())
2464
+ # on_disconnect cancels the producer when the client drops — no leak.
2465
+ return stream.response(on_disconnect=task.cancel)
2465
2466
  ```
2466
2467
 
2467
2468
  Browser side:
@@ -2473,6 +2474,8 @@ es.addEventListener("counter", (e) => console.log("got", JSON.parse(e.data)));
2473
2474
 
2474
2475
  `heartbeat_seconds` emits a `: keepalive` SSE comment when idle so load-balancers don't close long-lived connections. `ServerSentEvent.data` accepts strings, bytes or any JSON-serializable Python object — non-strings are JSON-encoded automatically. Pass `retry=` to hint the browser at the reconnect delay (milliseconds).
2475
2476
 
2477
+ The queue is **bounded** (`max_queue`, default `1000`): a slow client can't grow memory without limit. `overflow` picks the eviction policy — `"drop_oldest"` (default), `"drop_newest"`, or `"block"` (real backpressure); `EventStream.dropped_events` counts the discards. For broadcast, `SSEBroker.response(channel)` bundles `register` + `sse_response` + `unregister`-on-disconnect in one call. Authenticating an `EventSource` (which can't send an `Authorization` header): prefer a session cookie (`make_jwt_user_dependency(..., cookie_name="access_token")` + `withCredentials`); for cookieless clients pass a short-lived access token in the query string with `query_param="access_token"` (over TLS, scrubbed from logs). See the [SSE recipe](https://mauriciobenjamin700.github.io/tempest-fastapi-sdk/recipes/sse/) for the full guide.
2478
+
2476
2479
  ### Web Push notifications recipe
2477
2480
 
2478
2481
  `WebPushDispatcher` wraps the synchronous `pywebpush` library in `asyncio.to_thread` and surfaces the two errors the application cares about: `WebPushGoneError` (HTTP 404/410 — delete the subscription) and `WebPushError` (everything else). Install with `[webpush]`.
@@ -91,7 +91,7 @@ Via `pyproject.toml`:
91
91
 
92
92
  ```toml
93
93
  dependencies = [
94
- "tempest-fastapi-sdk>=0.90.0",
94
+ "tempest-fastapi-sdk>=0.91.0",
95
95
  ]
96
96
  ```
97
97
 
@@ -144,12 +144,12 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
144
144
  | `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException`, i18n (`MessageCatalog`, `default_message_catalog`, `parse_accept_language`, `DEFAULT_LOCALE`) |
145
145
  | `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
146
146
  | `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` (+ `RateLimitStore`/`MemoryRateLimitStore`/`RedisRateLimitStore`/`RateLimitResult` and `key_by_ip`/`key_by_jwt_subject`/`key_by_jwt_claim`/`key_by_header`), `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `GracefulShutdownMiddleware`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
147
- | `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + TOTP 2FA out of the box |
147
+ | `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, email change/verify/recovery (`EmailChangeRequestSchema` / `EmailChangeConfirmSchema` / `EmailRecoveryRequestSchema` / `EmailChangeToken` / `EmailVerificationToken`, old-email security notice, opt-in `AUTH_EMAIL_RECOVERY_ENABLED`), MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + email change/recovery + TOTP 2FA out of the box |
148
148
  | `tempest_fastapi_sdk.controllers` | `BaseController` |
149
149
  | `tempest_fastapi_sdk.services` | `BaseService` |
150
150
  | `tempest_fastapi_sdk.core` | `configure_logging`, `JSONFormatter`, `get_request_id`/`set_request_id`/`clear_request_id`, `request_id_ctx`, `BaseStrEnum`, `BaseIntEnum`, `strict_types`/`typed`/`require_annotations` |
151
151
  | `tempest_fastapi_sdk.admin` *(extra: `[admin]`)* | `AdminSite`, `AdminModel`, `make_admin_router`, `AdminAuthBackend`, `UserModelAuthBackend`, `AdminAuthError` |
152
- | `tempest_fastapi_sdk.sse` | `EventStream`, `SSEBroker` (multi-worker fan-out via Redis), `ServerSentEvent`, `sse_response` |
152
+ | `tempest_fastapi_sdk.sse` | `EventStream` (bounded queue + `overflow` backpressure), `SSEBroker` (multi-worker fan-out via Redis, `.response()` lifecycle helper), `ServerSentEvent`, `sse_response` (`on_disconnect=` cleanup) |
153
153
  | `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
154
154
  | `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
155
155
  | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `make_web_push_router`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
@@ -2336,7 +2336,7 @@ import asyncio
2336
2336
 
2337
2337
  from fastapi import APIRouter
2338
2338
 
2339
- from tempest_fastapi_sdk import EventStream, sse_response
2339
+ from tempest_fastapi_sdk import EventStream
2340
2340
 
2341
2341
  router = APIRouter()
2342
2342
 
@@ -2351,8 +2351,9 @@ async def events() -> "StreamingResponse": # forward-declared by Starlette
2351
2351
  await asyncio.sleep(1)
2352
2352
  await stream.close()
2353
2353
 
2354
- asyncio.create_task(producer())
2355
- return sse_response(stream.stream())
2354
+ task = asyncio.create_task(producer())
2355
+ # on_disconnect cancels the producer when the client drops — no leak.
2356
+ return stream.response(on_disconnect=task.cancel)
2356
2357
  ```
2357
2358
 
2358
2359
  Browser side:
@@ -2364,6 +2365,8 @@ es.addEventListener("counter", (e) => console.log("got", JSON.parse(e.data)));
2364
2365
 
2365
2366
  `heartbeat_seconds` emits a `: keepalive` SSE comment when idle so load-balancers don't close long-lived connections. `ServerSentEvent.data` accepts strings, bytes or any JSON-serializable Python object — non-strings are JSON-encoded automatically. Pass `retry=` to hint the browser at the reconnect delay (milliseconds).
2366
2367
 
2368
+ The queue is **bounded** (`max_queue`, default `1000`): a slow client can't grow memory without limit. `overflow` picks the eviction policy — `"drop_oldest"` (default), `"drop_newest"`, or `"block"` (real backpressure); `EventStream.dropped_events` counts the discards. For broadcast, `SSEBroker.response(channel)` bundles `register` + `sse_response` + `unregister`-on-disconnect in one call. Authenticating an `EventSource` (which can't send an `Authorization` header): prefer a session cookie (`make_jwt_user_dependency(..., cookie_name="access_token")` + `withCredentials`); for cookieless clients pass a short-lived access token in the query string with `query_param="access_token"` (over TLS, scrubbed from logs). See the [SSE recipe](https://mauriciobenjamin700.github.io/tempest-fastapi-sdk/recipes/sse/) for the full guide.
2369
+
2367
2370
  ### Web Push notifications recipe
2368
2371
 
2369
2372
  `WebPushDispatcher` wraps the synchronous `pywebpush` library in `asyncio.to_thread` and surfaces the two errors the application cares about: `WebPushGoneError` (HTTP 404/410 — delete the subscription) and `WebPushError` (everything else). Install with `[webpush]`.
@@ -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**. The release sections are listed newest-first, so on a multi-version jump read and apply them bottom-up.
4
4
 
5
+ ## 0.92.0 — `payload` column on the user token
6
+
7
+ 0.92.0 adds the **email change / re-verification / recovery** flow. To carry the pending email until confirmation, `BaseUserTokenModel` gained a new column:
8
+
9
+ ```python
10
+ payload: Mapped[str | None] = mapped_column(String(320), nullable=True, default=None)
11
+ ```
12
+
13
+ Since your `user_tokens` table inherits from `BaseUserTokenModel`, the column shows up on the model automatically — but the database needs a **migration**. It is additive and safe (nullable column, no required default):
14
+
15
+ ```bash
16
+ # generate and apply
17
+ tempest db revision -m "add payload to user_tokens"
18
+ tempest db upgrade
19
+ ```
20
+
21
+ Or by hand:
22
+
23
+ ```sql
24
+ ALTER TABLE user_tokens ADD COLUMN payload VARCHAR(320) NULL;
25
+ ```
26
+
27
+ !!! info "That's it"
28
+ No renames, no default backfill. Existing flows (activation, password reset) keep writing `payload = NULL`. The new email flow is fully opt-in — recovery (`POST /auth/email-recovery/request`) is only mounted with `AUTH_EMAIL_RECOVERY_ENABLED=True`.
29
+
30
+ ### Verify
31
+
32
+ - Run the migration before deploying 0.92.0 (the column must exist).
33
+ - If you hand-write `src/db/models/user_token.py` instead of using `make_user_token_model`, the column comes from the abstract base — no need to redeclare, just migrate.
34
+
5
35
  ## 0.63.0 — authenticated user loaded on the request session
6
36
 
7
37
  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
@@ -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. As seções estão listadas da mais nova para a mais antiga, então num salto de várias versões leia e aplique-as de baixo para cima.
4
4
 
5
+ ## 0.92.0 — coluna `payload` no token de usuário
6
+
7
+ A 0.92.0 adiciona o fluxo de **troca / re-verificação / recuperação de e-mail**. Para carregar o e-mail pendente até a confirmação, `BaseUserTokenModel` ganhou uma coluna nova:
8
+
9
+ ```python
10
+ payload: Mapped[str | None] = mapped_column(String(320), nullable=True, default=None)
11
+ ```
12
+
13
+ Como sua tabela `user_tokens` herda de `BaseUserTokenModel`, a coluna aparece automaticamente no modelo — mas o banco precisa de uma **migration**. É aditiva e segura (coluna anulável, sem default obrigatório):
14
+
15
+ ```bash
16
+ # gere e aplique
17
+ tempest db revision -m "add payload to user_tokens"
18
+ tempest db upgrade
19
+ ```
20
+
21
+ Ou, na mão:
22
+
23
+ ```sql
24
+ ALTER TABLE user_tokens ADD COLUMN payload VARCHAR(320) NULL;
25
+ ```
26
+
27
+ !!! info "Só isso"
28
+ Nenhuma renomeação, nenhum default backfill. Fluxos existentes (ativação, reset de senha) continuam gravando `payload = NULL`. O novo fluxo de e-mail é totalmente opt-in — a recuperação (`POST /auth/email-recovery/request`) só é montada com `AUTH_EMAIL_RECOVERY_ENABLED=True`.
29
+
30
+ ### Verifique
31
+
32
+ - Rode a migration antes de subir a 0.92.0 (a coluna precisa existir).
33
+ - Se você escreve `src/db/models/user_token.py` à mão em vez de usar `make_user_token_model`, a coluna vem da base abstrata — não precisa redeclarar, só migrar.
34
+
5
35
  ## 0.63.0 — usuário autenticado carregado na sessão de request
6
36
 
7
37
  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
@@ -130,6 +130,11 @@ uv run tempest db upgrade
130
130
  | POST | `/auth/password-reset/request` | `PasswordResetRequestSchema` → `PasswordResetResponseSchema` | Always HTTP 202 + generic body. Link via email (A/B) or body (C). |
131
131
  | POST | `/auth/password-reset/confirm` | `PasswordResetConfirmSchema` → `LoginResponseSchema` | Consumes token + writes new password + issues JWT pair. |
132
132
  | POST | `/auth/password-change` | `PasswordChangeSchema` → `204` | **Authenticated** (bearer token). Change your own password: confirm the current password + write the new one. No email token. |
133
+ | POST | `/auth/email-change/request` *(v0.92.0+)* | `EmailChangeRequestSchema` → `EmailChangeResponseSchema` | **Authenticated.** Confirm the current password + email a confirmation link to the **new** address. Always 202. |
134
+ | POST | `/auth/email-change/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consume the token + apply the new email + (optionally) notify the old address. |
135
+ | POST | `/auth/email-verify/request` *(v0.92.0+)* | — → `EmailChangeResponseSchema` | **Authenticated.** Re-send a verification link to the **current** email. |
136
+ | POST | `/auth/email-verify/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consume the token + mark the account active. |
137
+ | POST | `/auth/email-recovery/request` *(v0.92.0+, opt-in)* | `EmailRecoveryRequestSchema` → `EmailChangeResponseSchema` | **Unauthenticated.** Recover an account whose mailbox is lost: password (+ MFA if enrolled). Only mounted with `AUTH_EMAIL_RECOVERY_ENABLED=True`. Always 202. |
133
138
  | POST | `/auth/refresh` *(v0.65.0+)* | `RefreshSchema` → `LoginResponseSchema` | Exchange a valid **refresh token** for a fresh JWT pair. **No email/password.** Rejects a replayed access token (401) and inactive accounts (403). |
134
139
 
135
140
  !!! tip "`password-reset/confirm` vs `password-change` — which is which?"
@@ -145,6 +150,50 @@ uv run tempest db upgrade
145
150
  `current_password`. No email or reset token involved. Returns
146
151
  **204** and the current tokens stay valid.
147
152
 
153
+ ## Email change, verification and recovery (v0.92.0+)
154
+
155
+ Mirrors the password flow, but for the account **email**. Three cases:
156
+
157
+ - **Change email (logged in)** — like `password-change`: the user is
158
+ logged in, confirms `current_password` and supplies `new_email`. A
159
+ confirmation link goes to the **new** address; the email only changes
160
+ once that link is confirmed. On confirmation a security notice is sent
161
+ to the **old** address (the banks/Google pattern).
162
+ - **Re-verify the current email** — re-send a verification link to the
163
+ current address (useful when the activation email was lost).
164
+ - **Recovery (lost mailbox access)** — an **unauthenticated** endpoint,
165
+ opt-in via `AUTH_EMAIL_RECOVERY_ENABLED`. Proves identity with the
166
+ password **and a valid MFA code when TOTP is enrolled**, then emails the
167
+ link to the new address.
168
+
169
+ ```python
170
+ # Change email (logged in) — token comes in the body in dev (mode C)
171
+ resp = await client.post(
172
+ "/auth/email-change/request",
173
+ json={"new_email": "new@example.com", "current_password": "current-pass"},
174
+ headers={"Authorization": f"Bearer {access_token}"},
175
+ )
176
+ confirm_url: str | None = resp.json()["confirm_url"] # None in prod (goes by email)
177
+
178
+ # ...user opens the link; the front extracts the token and confirms:
179
+ await client.post("/auth/email-change/confirm", json={"token": token})
180
+ ```
181
+
182
+ !!! danger "Recovery is sensitive — enable it deliberately"
183
+ `POST /auth/email-recovery/request` lets whoever has the password move
184
+ the account to another email **without** accessing the old mailbox. It
185
+ is only mounted with `AUTH_EMAIL_RECOVERY_ENABLED=True`. It always
186
+ answers a generic **202** (no account enumeration) and, when TOTP is
187
+ enrolled, requires a valid `mfa_code`. Keep
188
+ `AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` so the old address is always
189
+ alerted.
190
+
191
+ !!! info "Where the new email is stored"
192
+ The pending address travels in the token's `payload` column
193
+ (`EMAIL_CHANGE`), not on the `UserModel`. Confirmation re-reads the
194
+ `payload`, re-checks the address is still free (a request→confirm race
195
+ → **409**) and only then writes it. See the 0.92.0 migration note.
196
+
148
197
  ### Renewing the session with the refresh token
149
198
 
150
199
  The `access_token` is short-lived by design (`JWT_ACCESS_TTL_SECONDS`,
@@ -130,6 +130,11 @@ uv run tempest db upgrade
130
130
  | POST | `/auth/password-reset/request` | `PasswordResetRequestSchema` → `PasswordResetResponseSchema` | Sempre HTTP 202 + corpo genérico. Link via e-mail (A/B) ou no body (C). |
131
131
  | POST | `/auth/password-reset/confirm` | `PasswordResetConfirmSchema` → `LoginResponseSchema` | Consome token + grava nova senha + emite JWT pair. |
132
132
  | POST | `/auth/password-change` | `PasswordChangeSchema` → `204` | **Autenticado** (bearer token). Troca a própria senha: confirma a senha atual + grava a nova. Sem token de e-mail. |
133
+ | POST | `/auth/email-change/request` *(v0.92.0+)* | `EmailChangeRequestSchema` → `EmailChangeResponseSchema` | **Autenticado.** Confirma a senha atual + envia link de confirmação pro **novo** e-mail. Sempre 202. |
134
+ | POST | `/auth/email-change/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consome o token + aplica o novo e-mail + (opcional) avisa o e-mail antigo. |
135
+ | POST | `/auth/email-verify/request` *(v0.92.0+)* | — → `EmailChangeResponseSchema` | **Autenticado.** Reenvia link de verificação pro e-mail **atual**. |
136
+ | POST | `/auth/email-verify/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consome o token + marca a conta ativa. |
137
+ | POST | `/auth/email-recovery/request` *(v0.92.0+, opt-in)* | `EmailRecoveryRequestSchema` → `EmailChangeResponseSchema` | **Não autenticado.** Recupera conta cujo e-mail se perdeu: senha (+ MFA se inscrito). Só montado com `AUTH_EMAIL_RECOVERY_ENABLED=True`. Sempre 202. |
133
138
  | POST | `/auth/refresh` *(v0.65.0+)* | `RefreshSchema` → `LoginResponseSchema` | Troca um **refresh token** válido por um JWT pair novo. **Sem email/senha.** Rejeita access token replayado (401) e conta inativa (403). |
134
139
 
135
140
  !!! tip "`password-reset/confirm` vs `password-change` — qual é qual?"
@@ -144,6 +149,50 @@ uv run tempest db upgrade
144
149
  nem token de reset. Retorna **204** e os tokens atuais continuam
145
150
  válidos.
146
151
 
152
+ ## Troca, verificação e recuperação de e-mail (v0.92.0+)
153
+
154
+ Espelha o fluxo de senha, mas pro **e-mail** da conta. Três cenários:
155
+
156
+ - **Trocar e-mail (logado)** — como `password-change`: o usuário está
157
+ logado, confirma a `current_password` e informa o `new_email`. Um link
158
+ de confirmação vai pro **novo** endereço; o e-mail só muda quando esse
159
+ link é confirmado. Ao confirmar, um aviso de segurança vai pro endereço
160
+ **antigo** (padrão de bancos/Google).
161
+ - **Re-verificar o e-mail atual** — reenvia um link de verificação pro
162
+ endereço atual (útil quando o e-mail de ativação se perdeu).
163
+ - **Recuperação (perdeu acesso ao e-mail)** — endpoint **não
164
+ autenticado**, opt-in via `AUTH_EMAIL_RECOVERY_ENABLED`. Prova
165
+ identidade com a senha **e um código MFA quando o TOTP está inscrito**,
166
+ e manda o link pro novo endereço.
167
+
168
+ ```python
169
+ # Trocar e-mail (logado) — pega o token no body em dev (modo C)
170
+ resp = await client.post(
171
+ "/auth/email-change/request",
172
+ json={"new_email": "nova@example.com", "current_password": "senha-atual"},
173
+ headers={"Authorization": f"Bearer {access_token}"},
174
+ )
175
+ confirm_url: str | None = resp.json()["confirm_url"] # None em produção (vai por e-mail)
176
+
177
+ # ...usuário abre o link; o front extrai o token e confirma:
178
+ await client.post("/auth/email-change/confirm", json={"token": token})
179
+ ```
180
+
181
+ !!! danger "Recuperação é sensível — ligue com cuidado"
182
+ `POST /auth/email-recovery/request` deixa quem tem a senha mover a
183
+ conta pra outro e-mail **sem** acessar a caixa antiga. Só é montado
184
+ com `AUTH_EMAIL_RECOVERY_ENABLED=True`. Sempre responde **202**
185
+ genérico (não enumera contas) e, se o TOTP estiver inscrito, exige um
186
+ `mfa_code` válido. Mantenha `AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` pra o
187
+ endereço antigo sempre ser avisado.
188
+
189
+ !!! info "Onde o novo e-mail fica guardado"
190
+ O endereço pendente viaja na coluna `payload` do token
191
+ (`EMAIL_CHANGE`), não no `UserModel`. A confirmação relê o `payload`,
192
+ re-checa que o endereço ainda está livre (corrida entre pedido e
193
+ confirmação → **409**) e só então grava. Veja a nota de migração da
194
+ 0.92.0.
195
+
147
196
  ### Renovando a sessão com o refresh token
148
197
 
149
198
  O `access_token` é curto por design (`JWT_ACCESS_TTL_SECONDS`, 1 h por