tempest-fastapi-sdk 0.93.0__tar.gz → 0.95.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 (519) hide show
  1. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/CHANGELOG.md +55 -0
  2. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/CLAUDE.md +15 -5
  3. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/PKG-INFO +4 -4
  4. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/README.md +3 -3
  5. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/auth-flow.en.md +173 -32
  6. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/auth-flow.md +172 -31
  7. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/cache.en.md +79 -0
  8. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/cache.md +78 -0
  9. tempest_fastapi_sdk-0.95.0/docs/recipes/fields.en.md +225 -0
  10. tempest_fastapi_sdk-0.95.0/docs/recipes/fields.md +225 -0
  11. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/queue-tasks.en.md +134 -7
  12. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/queue-tasks.md +134 -7
  13. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/pyproject.toml +1 -1
  14. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/__init__.py +11 -1
  15. tempest_fastapi_sdk-0.95.0/tempest_fastapi_sdk/queue/__init__.py +24 -0
  16. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/queue/broker.py +51 -0
  17. tempest_fastapi_sdk-0.95.0/tempest_fastapi_sdk/queue/consumer.py +200 -0
  18. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/queue/manager.py +22 -9
  19. tempest_fastapi_sdk-0.95.0/tempest_fastapi_sdk/tasks/__init__.py +75 -0
  20. tempest_fastapi_sdk-0.95.0/tempest_fastapi_sdk/tasks/cron.py +267 -0
  21. tempest_fastapi_sdk-0.95.0/tempest_fastapi_sdk/tasks/oop.py +187 -0
  22. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/tasks/queue.py +52 -4
  23. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/tasks/scheduler.py +9 -2
  24. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/__init__.py +10 -0
  25. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/regex.py +119 -0
  26. tempest_fastapi_sdk-0.95.0/tests/queue/test_consumer.py +102 -0
  27. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/queue/test_manager.py +10 -0
  28. tempest_fastapi_sdk-0.95.0/tests/tasks/test_cron.py +111 -0
  29. tempest_fastapi_sdk-0.95.0/tests/tasks/test_oop.py +75 -0
  30. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_regex.py +77 -0
  31. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/uv.lock +1 -1
  32. tempest_fastapi_sdk-0.93.0/docs/recipes/fields.en.md +0 -88
  33. tempest_fastapi_sdk-0.93.0/docs/recipes/fields.md +0 -88
  34. tempest_fastapi_sdk-0.93.0/tempest_fastapi_sdk/queue/__init__.py +0 -17
  35. tempest_fastapi_sdk-0.93.0/tempest_fastapi_sdk/tasks/__init__.py +0 -23
  36. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/.github/workflows/ci.yml +0 -0
  37. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/.github/workflows/docs.yml +0 -0
  38. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/.github/workflows/release-pypi.yml +0 -0
  39. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/.gitignore +0 -0
  40. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/.python-version +0 -0
  41. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/Makefile +0 -0
  42. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/architecture.en.md +0 -0
  43. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/architecture.md +0 -0
  44. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/changelog.en.md +0 -0
  45. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/changelog.md +0 -0
  46. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/contributing.en.md +0 -0
  47. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/contributing.md +0 -0
  48. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/index.en.md +0 -0
  49. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/index.md +0 -0
  50. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/installation.en.md +0 -0
  51. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/installation.md +0 -0
  52. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/index.en.md +0 -0
  53. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/index.md +0 -0
  54. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/api.en.md +0 -0
  55. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/api.md +0 -0
  56. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/business-rules.en.md +0 -0
  57. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/business-rules.md +0 -0
  58. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/domain.en.md +0 -0
  59. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/domain.md +0 -0
  60. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/flows.en.md +0 -0
  61. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/flows.md +0 -0
  62. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/index.en.md +0 -0
  63. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/learning/marketplace/index.md +0 -0
  64. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/migration.en.md +0 -0
  65. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/migration.md +0 -0
  66. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/admin.en.md +0 -0
  67. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/admin.md +0 -0
  68. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/audit-trail.en.md +0 -0
  69. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/audit-trail.md +0 -0
  70. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/br-helpers.en.md +0 -0
  71. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/br-helpers.md +0 -0
  72. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/cli.en.md +0 -0
  73. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/cli.md +0 -0
  74. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/database.en.md +0 -0
  75. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/database.md +0 -0
  76. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/deploy-safety.en.md +0 -0
  77. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/deploy-safety.md +0 -0
  78. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/downloads.en.md +0 -0
  79. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/downloads.md +0 -0
  80. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/email.en.md +0 -0
  81. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/email.md +0 -0
  82. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/feature-flags.en.md +0 -0
  83. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/feature-flags.md +0 -0
  84. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/file-store.en.md +0 -0
  85. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/file-store.md +0 -0
  86. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/http-client.en.md +0 -0
  87. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/http-client.md +0 -0
  88. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/http.en.md +0 -0
  89. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/http.md +0 -0
  90. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/idempotency.en.md +0 -0
  91. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/idempotency.md +0 -0
  92. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/index.en.md +0 -0
  93. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/index.md +0 -0
  94. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/logging.en.md +0 -0
  95. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/logging.md +0 -0
  96. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/metrics.en.md +0 -0
  97. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/metrics.md +0 -0
  98. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/mfa.en.md +0 -0
  99. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/mfa.md +0 -0
  100. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/multi-tenant.en.md +0 -0
  101. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/multi-tenant.md +0 -0
  102. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/observability.en.md +0 -0
  103. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/observability.md +0 -0
  104. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/offline-sync.en.md +0 -0
  105. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/offline-sync.md +0 -0
  106. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/outbox.en.md +0 -0
  107. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/outbox.md +0 -0
  108. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/realtime.en.md +0 -0
  109. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/realtime.md +0 -0
  110. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/refresh-tokens.en.md +0 -0
  111. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/refresh-tokens.md +0 -0
  112. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/security.en.md +0 -0
  113. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/security.md +0 -0
  114. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/sessions.en.md +0 -0
  115. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/sessions.md +0 -0
  116. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/sse.en.md +0 -0
  117. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/sse.md +0 -0
  118. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/storage.en.md +0 -0
  119. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/storage.md +0 -0
  120. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/stored-files.en.md +0 -0
  121. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/stored-files.md +0 -0
  122. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/testing.en.md +0 -0
  123. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/testing.md +0 -0
  124. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/typing.en.md +0 -0
  125. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/typing.md +0 -0
  126. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/uploads.en.md +0 -0
  127. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/uploads.md +0 -0
  128. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/utilities.en.md +0 -0
  129. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/utilities.md +0 -0
  130. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/vision.en.md +0 -0
  131. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/vision.md +0 -0
  132. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/webpush.en.md +0 -0
  133. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/webpush.md +0 -0
  134. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/websocket.en.md +0 -0
  135. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/recipes/websocket.md +0 -0
  136. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/reference.en.md +0 -0
  137. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/reference.md +0 -0
  138. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/roadmap.en.md +0 -0
  139. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/roadmap.md +0 -0
  140. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/ssr.en.md +0 -0
  141. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/ssr.md +0 -0
  142. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/tutorial.en.md +0 -0
  143. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/docs/tutorial.md +0 -0
  144. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/mkdocs.yml +0 -0
  145. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/mkdocs_hooks/llmstxt.py +0 -0
  146. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/scripts/extract_recipe.py +0 -0
  147. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
  148. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/actions.py +0 -0
  149. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
  150. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/config.py +0 -0
  151. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/discovery.py +0 -0
  152. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
  153. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/router.py +0 -0
  154. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/session.py +0 -0
  155. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/site.py +0 -0
  156. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
  157. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
  158. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
  159. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
  160. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
  161. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
  162. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
  163. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
  164. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
  165. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/admin/theme.py +0 -0
  166. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
  167. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
  168. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
  169. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/dependencies/auth.py +0 -0
  170. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
  171. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
  172. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
  173. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
  174. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
  175. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
  176. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
  177. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
  178. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
  179. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
  180. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
  181. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
  182. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
  183. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
  184. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
  185. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/server.py +0 -0
  186. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/static.py +0 -0
  187. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
  188. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
  189. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/__init__.py +0 -0
  190. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
  191. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/locale.py +0 -0
  192. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
  193. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/router.py +0 -0
  194. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
  195. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/service.py +0 -0
  196. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
  197. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
  198. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
  199. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/email_change.html +0 -0
  200. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/email_change_error.html +0 -0
  201. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/email_change_success.html +0 -0
  202. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/email_changed_notice.html +0 -0
  203. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/email_verification.html +0 -0
  204. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/email_verification_error.html +0 -0
  205. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/email_verification_success.html +0 -0
  206. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
  207. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
  208. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
  209. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
  210. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
  211. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
  212. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
  213. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_change.html +0 -0
  214. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_error.html +0 -0
  215. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_success.html +0 -0
  216. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_changed_notice.html +0 -0
  217. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification.html +0 -0
  218. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_error.html +0 -0
  219. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_success.html +0 -0
  220. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
  221. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
  222. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
  223. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
  224. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/auth/token_delivery.py +0 -0
  225. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
  226. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
  227. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
  228. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
  229. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
  230. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/Dockerfile.tmpl +0 -0
  231. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
  232. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/dockerignore.tmpl +0 -0
  233. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
  234. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
  235. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
  236. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
  237. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
  238. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
  239. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
  240. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
  241. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
  242. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
  243. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
  244. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
  245. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
  246. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
  247. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
  248. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
  249. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
  250. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
  251. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
  252. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
  253. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
  254. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
  255. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
  256. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
  257. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
  258. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/config.py +0 -0
  259. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/db.py +0 -0
  260. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
  261. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
  262. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
  263. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/main.py +0 -0
  264. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/new.py +0 -0
  265. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
  266. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
  267. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/cli/user.py +0 -0
  268. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
  269. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
  270. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
  271. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/core/context.py +0 -0
  272. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/core/enums.py +0 -0
  273. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/core/logging.py +0 -0
  274. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/core/typed.py +0 -0
  275. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
  276. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
  277. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
  278. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
  279. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/audit.py +0 -0
  280. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/backup.py +0 -0
  281. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/connection.py +0 -0
  282. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
  283. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
  284. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/model.py +0 -0
  285. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
  286. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/repository.py +0 -0
  287. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
  288. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
  289. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
  290. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
  291. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/user_refresh_token_model.py +0 -0
  292. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
  293. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/db/webpush_subscription_model.py +0 -0
  294. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
  295. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
  296. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
  297. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
  298. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
  299. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
  300. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
  301. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
  302. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
  303. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
  304. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
  305. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
  306. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
  307. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
  308. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/flags/service.py +0 -0
  309. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/py.typed +0 -0
  310. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
  311. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
  312. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
  313. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
  314. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
  315. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
  316. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
  317. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/services/base.py +0 -0
  318. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/services/file_mixin.py +0 -0
  319. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
  320. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
  321. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
  322. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
  323. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
  324. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
  325. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
  326. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
  327. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/settings/base.py +0 -0
  328. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/settings/mixins.py +0 -0
  329. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sse/__init__.py +0 -0
  330. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sse/broker.py +0 -0
  331. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/sse/event_stream.py +0 -0
  332. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/ssr/__init__.py +0 -0
  333. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/ssr/_static/htmx.min.js +0 -0
  334. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/ssr/assets.py +0 -0
  335. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/ssr/page.py +0 -0
  336. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/ssr/response.py +0 -0
  337. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
  338. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
  339. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
  340. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
  341. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/testing/database.py +0 -0
  342. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
  343. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
  344. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
  345. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
  346. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/download.py +0 -0
  347. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/email.py +0 -0
  348. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/fields.py +0 -0
  349. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/file_store.py +0 -0
  350. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
  351. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
  352. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
  353. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/log.py +0 -0
  354. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
  355. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
  356. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/password.py +0 -0
  357. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
  358. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
  359. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
  360. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
  361. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/vision/__init__.py +0 -0
  362. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/vision/mapping.py +0 -0
  363. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/vision/schemas.py +0 -0
  364. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
  365. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
  366. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/webpush/router.py +0 -0
  367. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
  368. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/webpush/service.py +0 -0
  369. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
  370. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
  371. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
  372. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
  373. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/__init__.py +0 -0
  374. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/__init__.py +0 -0
  375. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_actions.py +0 -0
  376. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_auth.py +0 -0
  377. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_discovery.py +0 -0
  378. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_forms.py +0 -0
  379. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_logs_nav.py +0 -0
  380. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_mfa.py +0 -0
  381. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_rich_filters.py +0 -0
  382. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_router.py +0 -0
  383. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_site.py +0 -0
  384. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_theme.py +0 -0
  385. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_upload_field.py +0 -0
  386. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/admin/test_user_model.py +0 -0
  387. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/__init__.py +0 -0
  388. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_body_size.py +0 -0
  389. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_cookies.py +0 -0
  390. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_cors.py +0 -0
  391. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_csrf.py +0 -0
  392. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_dependencies_auth.py +0 -0
  393. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_graceful.py +0 -0
  394. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_handlers.py +0 -0
  395. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_health_router.py +0 -0
  396. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_idempotency.py +0 -0
  397. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_jwt_dependency.py +0 -0
  398. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_logs_router.py +0 -0
  399. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_oauth.py +0 -0
  400. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_prometheus.py +0 -0
  401. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_rate_limit.py +0 -0
  402. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_rate_limit_extras.py +0 -0
  403. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_request_id_middleware.py +0 -0
  404. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_role_dependency.py +0 -0
  405. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_server.py +0 -0
  406. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_static.py +0 -0
  407. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_tool_spec.py +0 -0
  408. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_tracing.py +0 -0
  409. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_webhooks.py +0 -0
  410. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/api/test_webhooks_rsa.py +0 -0
  411. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/__init__.py +0 -0
  412. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_cookie_delivery.py +0 -0
  413. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_email_change.py +0 -0
  414. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_guards.py +0 -0
  415. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_locale.py +0 -0
  416. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_mfa.py +0 -0
  417. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_refresh.py +0 -0
  418. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_refresh_db.py +0 -0
  419. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/auth/test_service.py +0 -0
  420. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cache/__init__.py +0 -0
  421. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cache/test_decorator.py +0 -0
  422. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cache/test_invalidation.py +0 -0
  423. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cache/test_redis_manager.py +0 -0
  424. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/__init__.py +0 -0
  425. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_config.py +0 -0
  426. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_db.py +0 -0
  427. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_db_seed.py +0 -0
  428. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_docker_compose.py +0 -0
  429. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_generate.py +0 -0
  430. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_lint_strictness.py +0 -0
  431. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_main.py +0 -0
  432. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_secrets.py +0 -0
  433. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/cli/test_user.py +0 -0
  434. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/conftest.py +0 -0
  435. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/controllers/__init__.py +0 -0
  436. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/controllers/test_base.py +0 -0
  437. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/core/__init__.py +0 -0
  438. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/core/test_context.py +0 -0
  439. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/core/test_enums.py +0 -0
  440. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/core/test_logging.py +0 -0
  441. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/core/test_typed.py +0 -0
  442. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/__init__.py +0 -0
  443. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_alembic_hooks.py +0 -0
  444. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_audit.py +0 -0
  445. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_backup.py +0 -0
  446. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_bulk_ops.py +0 -0
  447. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_connection.py +0 -0
  448. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_migrations.py +0 -0
  449. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_mixins.py +0 -0
  450. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_model.py +0 -0
  451. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_outbox.py +0 -0
  452. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_repository.py +0 -0
  453. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_safe_upgrade.py +0 -0
  454. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_slow_query.py +0 -0
  455. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/db/test_tenant.py +0 -0
  456. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/exceptions/__init__.py +0 -0
  457. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/exceptions/test_exceptions.py +0 -0
  458. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/exceptions/test_i18n.py +0 -0
  459. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/flags/__init__.py +0 -0
  460. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/flags/test_flags.py +0 -0
  461. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/queue/__init__.py +0 -0
  462. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/queue/test_broker.py +0 -0
  463. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/schemas/__init__.py +0 -0
  464. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/schemas/test_base.py +0 -0
  465. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/schemas/test_cursor_pagination.py +0 -0
  466. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/schemas/test_link_headers.py +0 -0
  467. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/schemas/test_pagination.py +0 -0
  468. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/schemas/test_response.py +0 -0
  469. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/services/__init__.py +0 -0
  470. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/services/test_base.py +0 -0
  471. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/services/test_file_mixin.py +0 -0
  472. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/sessions/__init__.py +0 -0
  473. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/sessions/test_sessions.py +0 -0
  474. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/settings/__init__.py +0 -0
  475. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/settings/test_base.py +0 -0
  476. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/settings/test_mixins.py +0 -0
  477. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/sse/__init__.py +0 -0
  478. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/sse/test_broker.py +0 -0
  479. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/sse/test_event_stream.py +0 -0
  480. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/ssr/__init__.py +0 -0
  481. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/ssr/test_integration.py +0 -0
  482. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/ssr/test_page.py +0 -0
  483. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/ssr/test_response.py +0 -0
  484. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/storage/__init__.py +0 -0
  485. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/storage/test_minio_client.py +0 -0
  486. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/tasks/__init__.py +0 -0
  487. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/tasks/test_manager.py +0 -0
  488. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/tasks/test_queue.py +0 -0
  489. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/tasks/test_scheduler.py +0 -0
  490. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/testing/__init__.py +0 -0
  491. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/testing/test_database.py +0 -0
  492. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/__init__.py +0 -0
  493. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_client_ip.py +0 -0
  494. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_datetime.py +0 -0
  495. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_dict.py +0 -0
  496. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_download.py +0 -0
  497. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_email.py +0 -0
  498. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_fields.py +0 -0
  499. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_file_store.py +0 -0
  500. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_http_client.py +0 -0
  501. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_jwt.py +0 -0
  502. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_lazy_extras.py +0 -0
  503. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_locations.py +0 -0
  504. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_log.py +0 -0
  505. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_metrics.py +0 -0
  506. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_opaque_token.py +0 -0
  507. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_password.py +0 -0
  508. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_storage_backends.py +0 -0
  509. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_throttle.py +0 -0
  510. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/utils/test_upload.py +0 -0
  511. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/vision/__init__.py +0 -0
  512. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/vision/test_vision.py +0 -0
  513. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/webpush/__init__.py +0 -0
  514. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/webpush/test_dispatcher.py +0 -0
  515. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/webpush/test_router.py +0 -0
  516. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/webpush/test_schemas.py +0 -0
  517. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/webpush/test_service.py +0 -0
  518. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/websockets/__init__.py +0 -0
  519. {tempest_fastapi_sdk-0.93.0 → tempest_fastapi_sdk-0.95.0}/tests/websockets/test_hub_and_router.py +0 -0
@@ -5,6 +5,61 @@ 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.95.0] — 2026-07-05
9
+
10
+ ### Added
11
+
12
+ - **PIX key field + helpers** (`tempest_fastapi_sdk.utils`). `PixKeyField`
13
+ is an `Annotated` schema type that validates any of the five BACEN PIX
14
+ key types (CPF, CNPJ, e-mail, E.164 phone, random UUID) in one field
15
+ and normalizes to a canonical form (CPF/CNPJ → digits, e-mail →
16
+ lowercase, phone → `+55…`, random → lowercase UUID). Companions:
17
+ `PixKeyType` (the enum), `detect_pix_key_type(value)` (returns the type
18
+ or `None`), `is_valid_pix_key(value)` and `normalize_pix_key(value)`.
19
+ Detection is by shape plus CPF/CNPJ check digits — all exported from the
20
+ package root.
21
+
22
+ ### Changed
23
+
24
+ - The **validated-fields recipe** was expanded (both locales): a full
25
+ schema + route + 422 walkthrough, a "compose your own field" section,
26
+ common gotchas (`CentsField` vs `PriceField`, `PercentField` vs
27
+ `RatioField`), and the new PIX-key section.
28
+
29
+ ## [0.94.0] — 2026-07-05
30
+
31
+ ### Added
32
+
33
+ - **Human-friendly cron helpers** (`tempest_fastapi_sdk.tasks`) — schedule
34
+ periodic tasks without writing cron syntax:
35
+ - `Cron` — ready-made expressions (`Cron.EVERY_WEEKDAY_9AM`,
36
+ `Cron.EVERY_5_MINUTES`, …).
37
+ - `CronOffset` — timezone offsets by place (`CronOffset.BRASILIA` =
38
+ `-03:00`, plus `FERNANDO_DE_NORONHA` / `MANAUS` / `ACRE` / `UTC`).
39
+ - `Weekday` — day-of-week tokens.
40
+ - Builder functions — `daily`, `weekdays`, `weekends`, `hourly`,
41
+ `every_minute`, `every_n_minutes`, `weekly`, `monthly` — each
42
+ returning a plain cron string with range validation.
43
+ - `@tq.cron(...)` / `AsyncTaskScheduler.cron(...)` accept these
44
+ directly, coercing enum members to their plain string value. The
45
+ module has no third-party dependency (imports without `[tasks]`).
46
+ - **Class-based message consumers** (`tempest_fastapi_sdk.queue`) — an
47
+ alternative to the `@mq.on` decorator, in two explicit styles:
48
+ `Consumer` with a constructor `channel=` + Pydantic `schema=` (no
49
+ annotation-sniffing) and overridden `handle`, or grouped `@subscribe`
50
+ methods (one class, many channels). Wire with `MessageBroker.register`.
51
+ - **Class-based background tasks** (`tempest_fastapi_sdk.tasks`) —
52
+ symmetric to consumers: `TaskDef` with an overridden `run` (name in the
53
+ constructor) or grouped `@task_method` methods, wired with
54
+ `TaskQueue.register` (returns a `Task` or a `dict[str, Task]`).
55
+
56
+ ### Changed
57
+
58
+ - **`AsyncBrokerManager` renamed to `AsyncQueueManager`** — a clearer name
59
+ for the thin lifecycle wrapper around an injected broker, matching the
60
+ `Async*Manager` family. `AsyncBrokerManager` stays as a backward-compatible
61
+ alias. `MessageBroker` remains the recommended batteries-included facade.
62
+
8
63
  ## [0.93.0] — 2026-07-05
9
64
 
10
65
  ### Added
@@ -162,13 +162,23 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
162
162
  consumer, channel-first `publish(channel, message)`, `.broker` escape
163
163
  hatch) and `TaskQueue` (`.rabbitmq`/`.redis`/`.memory`, `@tq.task` →
164
164
  `Task.enqueue`/`.run`, folded `@tq.cron`/`@tq.interval` +
165
- `start_scheduler`, `tq.broker`/`tq.scheduler` for the CLIs). Legacy
166
- `AsyncBrokerManager`/`AsyncTaskBrokerManager`/`AsyncTaskScheduler` kept
167
- as working aliases. Outbox (`BaseOutboxModel`/`OutboxRelay`/
168
- `save_with_outbox`) plugs its `publish` into `MessageBroker.publish`.
165
+ `start_scheduler`, `tq.broker`/`tq.scheduler` for the CLIs). **Both
166
+ decorator and class-based styles**: `Consumer` + `@subscribe` +
167
+ `MessageBroker.register` (constructor form takes explicit
168
+ `channel`+`schema`, no magic); `TaskDef` + `@task_method` +
169
+ `TaskQueue.register`. **Cron without syntax**: `Cron`/`CronOffset`
170
+ (`BRASILIA` etc.)/`Weekday` enums + `daily`/`weekdays`/`every_n_minutes`/
171
+ `weekly`/`monthly`/… builders (dependency-free). `AsyncBrokerManager`
172
+ renamed to **`AsyncQueueManager`** (v0.94.0; old alias kept); legacy
173
+ `AsyncTaskBrokerManager`/`AsyncTaskScheduler` kept. Outbox
174
+ (`BaseOutboxModel`/`OutboxRelay`/`save_with_outbox`) plugs its `publish`
175
+ into `MessageBroker.publish`.
169
176
  - **BR validators** — CPF/CNPJ/CEP/phone, with `*Field` Pydantic types
170
177
  (`CPFField`/`CNPJField`/`CPFOrCNPJField`/`PhoneBRField`/`CEPField`;
171
- pre-0.76 unsuffixed names kept as deprecated aliases).
178
+ pre-0.76 unsuffixed names kept as deprecated aliases). **PIX keys**
179
+ (v0.95.0): `PixKeyField` validates+normalizes any of the 5 BACEN key
180
+ types (CPF/CNPJ/email/E.164 phone/random UUID); `PixKeyType` +
181
+ `detect_pix_key_type`/`is_valid_pix_key`/`normalize_pix_key`.
172
182
  - **BR localities** — `UF` (StrEnum, 27 siglas) + `Region`
173
183
  (5 macro-regiões IBGE), `StateBR`/`CityBR` schemas, offline
174
184
  dataset of 27 states + 5606 municipalities (IBGE-derived,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tempest-fastapi-sdk
3
- Version: 0.93.0
3
+ Version: 0.95.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
@@ -262,14 +262,14 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
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` |
265
- | `tempest_fastapi_sdk.queue` *(extra: `[queue]`)* | `MessageBroker` (typed, transport-agnostic FastStream facade — `.rabbitmq`/`.redis`/`.kafka`/`.nats`, `@mq.on(channel)`, channel-first `publish`); `AsyncBrokerManager` (legacy lifecycle wrapper) |
265
+ | `tempest_fastapi_sdk.queue` *(extra: `[queue]`)* | `MessageBroker` (typed, transport-agnostic FastStream facade — `.rabbitmq`/`.redis`/`.kafka`/`.nats`, `@mq.on(channel)`, channel-first `publish`); class-based consumers (`Consumer` + `@subscribe` + `MessageBroker.register`); `AsyncQueueManager` (thin lifecycle wrapper, formerly `AsyncBrokerManager`) |
266
266
  | `tempest_fastapi_sdk.storage` *(extra: `[minio]`)* | `AsyncMinIOClient`, `ObjectStat` — async MinIO/S3 facade |
267
267
  | `tempest_fastapi_sdk.utils.http_client` *(extra: `[http]`)* | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, `REQUEST_ID_HEADER` — typed httpx wrapper |
268
268
  | `tempest_fastapi_sdk.utils.storage_backends` *(extra: `[upload]`)* | `UploadStorage` protocol, `LocalUploadStorage`, `MinIOUploadStorage`, `UploadResult`, `ContentValidator` |
269
- | `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `TaskQueue` (typed TaskIQ facade — `.rabbitmq`/`.redis`/`.memory`, `@tq.task` → `Task.enqueue`/`.run`, `@tq.cron`/`@tq.interval`, `start_scheduler`), `Task`; `AsyncTaskBrokerManager` / `AsyncTaskScheduler` (legacy wrappers) |
269
+ | `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `TaskQueue` (typed TaskIQ facade — `.rabbitmq`/`.redis`/`.memory`, `@tq.task` → `Task.enqueue`/`.run`, `@tq.cron`/`@tq.interval`, `start_scheduler`), `Task`; class-based tasks (`TaskDef` + `@task_method` + `TaskQueue.register`); cron helpers (`Cron` / `CronOffset` / `Weekday` + `daily`/`weekdays`/`every_n_minutes`/… builders); `AsyncTaskBrokerManager` / `AsyncTaskScheduler` (legacy wrappers) |
270
270
  | `tempest_fastapi_sdk.vision` *(extra: `[vision]`)* | `Detector`, `Classifier`, `Segmenter` (ONNX, lazy), `DetectionSchema`/`ClassificationSchema`/`SegmentationSchema`/`BoundingBoxSchema`/`ClassProbabilitySchema`, `to_detection_schemas`/`to_classification_schema`/`to_segmentation_schemas` |
271
271
  | `tempest_fastapi_sdk.ssr` *(extra: `[ssr]`)* | `Page` (typed component base), `html_response` (widget tree → `HTMLResponse`, full document or HTMX fragment), `make_htmx_router` (serves bundled HTMX locally, no CDN) |
272
- | `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `FileStoreUtils` — unified upload+download+presign facade *(extra: `[upload]` local / `[minio]` MinIO)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField` — old names without the suffix kept as deprecated aliases — `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
272
+ | `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `FileStoreUtils` — unified upload+download+presign facade *(extra: `[upload]` local / `[minio]` MinIO)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField`, `PixKeyField` — old names without the suffix kept as deprecated aliases — `PixKeyType`/`detect_pix_key_type`/`is_valid_pix_key`, `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
273
273
  | `tempest_fastapi_sdk.cli` | `tempest` console script — `new <name>` (scaffold layered service), `lint` / `format` / `fmt-check` / `type` / `test` / `check` (run preferred quality gates), `version` / `--version` |
274
274
 
275
275
  Core primitives are re-exported from `tempest_fastapi_sdk` at the top level — `from tempest_fastapi_sdk import BaseModel, BaseRepository, AppException` always works. The extras-gated managers in `tempest_fastapi_sdk.cache`, `tempest_fastapi_sdk.queue`, `tempest_fastapi_sdk.tasks`, `tempest_fastapi_sdk.vision` and `tempest_fastapi_sdk.ssr` must be imported from their own submodule (`from tempest_fastapi_sdk.queue import MessageBroker`).
@@ -153,14 +153,14 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
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` |
156
- | `tempest_fastapi_sdk.queue` *(extra: `[queue]`)* | `MessageBroker` (typed, transport-agnostic FastStream facade — `.rabbitmq`/`.redis`/`.kafka`/`.nats`, `@mq.on(channel)`, channel-first `publish`); `AsyncBrokerManager` (legacy lifecycle wrapper) |
156
+ | `tempest_fastapi_sdk.queue` *(extra: `[queue]`)* | `MessageBroker` (typed, transport-agnostic FastStream facade — `.rabbitmq`/`.redis`/`.kafka`/`.nats`, `@mq.on(channel)`, channel-first `publish`); class-based consumers (`Consumer` + `@subscribe` + `MessageBroker.register`); `AsyncQueueManager` (thin lifecycle wrapper, formerly `AsyncBrokerManager`) |
157
157
  | `tempest_fastapi_sdk.storage` *(extra: `[minio]`)* | `AsyncMinIOClient`, `ObjectStat` — async MinIO/S3 facade |
158
158
  | `tempest_fastapi_sdk.utils.http_client` *(extra: `[http]`)* | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, `REQUEST_ID_HEADER` — typed httpx wrapper |
159
159
  | `tempest_fastapi_sdk.utils.storage_backends` *(extra: `[upload]`)* | `UploadStorage` protocol, `LocalUploadStorage`, `MinIOUploadStorage`, `UploadResult`, `ContentValidator` |
160
- | `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `TaskQueue` (typed TaskIQ facade — `.rabbitmq`/`.redis`/`.memory`, `@tq.task` → `Task.enqueue`/`.run`, `@tq.cron`/`@tq.interval`, `start_scheduler`), `Task`; `AsyncTaskBrokerManager` / `AsyncTaskScheduler` (legacy wrappers) |
160
+ | `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `TaskQueue` (typed TaskIQ facade — `.rabbitmq`/`.redis`/`.memory`, `@tq.task` → `Task.enqueue`/`.run`, `@tq.cron`/`@tq.interval`, `start_scheduler`), `Task`; class-based tasks (`TaskDef` + `@task_method` + `TaskQueue.register`); cron helpers (`Cron` / `CronOffset` / `Weekday` + `daily`/`weekdays`/`every_n_minutes`/… builders); `AsyncTaskBrokerManager` / `AsyncTaskScheduler` (legacy wrappers) |
161
161
  | `tempest_fastapi_sdk.vision` *(extra: `[vision]`)* | `Detector`, `Classifier`, `Segmenter` (ONNX, lazy), `DetectionSchema`/`ClassificationSchema`/`SegmentationSchema`/`BoundingBoxSchema`/`ClassProbabilitySchema`, `to_detection_schemas`/`to_classification_schema`/`to_segmentation_schemas` |
162
162
  | `tempest_fastapi_sdk.ssr` *(extra: `[ssr]`)* | `Page` (typed component base), `html_response` (widget tree → `HTMLResponse`, full document or HTMX fragment), `make_htmx_router` (serves bundled HTMX locally, no CDN) |
163
- | `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `FileStoreUtils` — unified upload+download+presign facade *(extra: `[upload]` local / `[minio]` MinIO)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField` — old names without the suffix kept as deprecated aliases — `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
163
+ | `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `FileStoreUtils` — unified upload+download+presign facade *(extra: `[upload]` local / `[minio]` MinIO)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField`, `PixKeyField` — old names without the suffix kept as deprecated aliases — `PixKeyType`/`detect_pix_key_type`/`is_valid_pix_key`, `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
164
164
  | `tempest_fastapi_sdk.cli` | `tempest` console script — `new <name>` (scaffold layered service), `lint` / `format` / `fmt-check` / `type` / `test` / `check` (run preferred quality gates), `version` / `--version` |
165
165
 
166
166
  Core primitives are re-exported from `tempest_fastapi_sdk` at the top level — `from tempest_fastapi_sdk import BaseModel, BaseRepository, AppException` always works. The extras-gated managers in `tempest_fastapi_sdk.cache`, `tempest_fastapi_sdk.queue`, `tempest_fastapi_sdk.tasks`, `tempest_fastapi_sdk.vision` and `tempest_fastapi_sdk.ssr` must be imported from their own submodule (`from tempest_fastapi_sdk.queue import MessageBroker`).
@@ -2,12 +2,32 @@
2
2
 
3
3
  Since v0.31.0 the SDK ships the full local-account lifecycle — email + password signup, link-based activation, JWT-pair login, password reset — via `UserAuthService` + `make_auth_router`. **Endpoints ready to mount** (including `POST /auth/refresh` since v0.65.0), Jinja2 templates bundled, settings flags decide whether the link is emailed or returned in the response body, and four pre-thought modes for dev / staging / production / CI.
4
4
 
5
+ !!! tip "Jump straight to your case"
6
+ The table below maps **what the user wants to do** → the section and
7
+ endpoints. Start at your case; come back to [setup](#minimum-setup)
8
+ only when you need to wire the pieces.
9
+
10
+ | I want to… | Logged in? | Section | Endpoints |
11
+ | --- | --- | --- | --- |
12
+ | Create account + activate by email | — | [Setup](#minimum-setup) | `signup` → `activate/{token}` |
13
+ | Log in | — | [Endpoints](#endpoints) | `login` |
14
+ | **I forgot my password** | ❌ no | **[Password recovery](#password-recovery)** | `password-reset/request` → `password-reset/confirm` |
15
+ | Change my password | ✅ yes | [Change password logged in](#change-your-password-logged-in) | `password-change` |
16
+ | Change my email | ✅ yes | [Change email](#change-email-logged-in) | `email-change/request` → `email-change/confirm` |
17
+ | Re-verify my current email | ✅ yes | [Re-verify email](#re-verify-the-current-email) | `email-verify/request` → `email-verify/confirm` |
18
+ | **I lost access to my email** | ❌ no | **[Email recovery](#email-recovery)** | `email-recovery/request` → `email-change/confirm` |
19
+ | My session expired | — | [Refresh](#renewing-the-session-with-the-refresh-token) | `refresh` |
20
+
21
+ **The two "I forgot"**: lost password → [Password recovery](#password-recovery); lost mailbox → [Email recovery](#email-recovery).
22
+
5
23
  ## Recipe contents
6
24
 
7
25
  1. **[Minimum setup](#minimum-setup)** — extras install + wiring four objects (`AsyncDatabaseManager`, `EmailUtils`, `UserAuthService`, `make_auth_router`).
8
26
  2. **[Concrete UserTokenModel](#concrete-usertokenmodel)** — `BaseUserTokenModel` is abstract, your project owns the concrete table.
9
- 3. **[Endpoints](#endpoints)** — table of the 5 endpoints + payload + behavior.
10
- 4. **[Settings — environment variables](#settings-environment-variables)** — env vars in **six groups** (JWT, password policy, email flow, TTL, URLs/templates, backend pages) each in a typed table, not one blob.
27
+ 3. **[Endpoints](#endpoints)** — table of all endpoints + payload + behavior.
28
+ 4. **[Password recovery](#password-recovery)** — the "forgot password" flow, step by step, plus changing the password while logged in.
29
+ 5. **[Email change and recovery](#email-change-and-recovery)** — change email logged in, re-verify, and recover when the mailbox is lost.
30
+ 6. **[Settings — environment variables](#settings-environment-variables)** — env vars in **groups** (JWT, password policy, email flow, TTL, URLs/templates, backend pages) — each in a typed table, not one blob.
11
31
  5. **[Email anatomy: how link, template and URL fit together](#email-anatomy)** — disambiguates the three concepts that confuse readers the most.
12
32
  6. **[Five operating modes](#five-operating-modes)** — production, dev with local SMTP (Mailhog / smtp4dev), dev without SMTP, CI without activation, and **backend-only** (links and pages served directly by the backend).
13
33
  7. **[Mailhog vs smtp4dev — which to pick for local dev](#mailhog-vs-smtp4dev)** — comparison + copy-paste docker-compose snippets.
@@ -150,43 +170,164 @@ uv run tempest db upgrade
150
170
  `current_password`. No email or reset token involved. Returns
151
171
  **204** and the current tokens stay valid.
152
172
 
153
- ## Email change, verification and recovery (v0.92.0+)
173
+ ## Password recovery
154
174
 
155
- Mirrors the password flow, but for the account **email**. Three cases:
175
+ The classic "I forgot my password". The user is **not logged in** and
176
+ proves identity with a **single-use token** delivered by email. Two steps.
156
177
 
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.
178
+ ### Base case (SPA / JSON)
168
179
 
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)
180
+ **Step 1 — request the link.** The user types their email; the backend
181
+ always answers **202** with the same generic message (it never leaks
182
+ whether the email exists):
183
+
184
+ ```bash
185
+ curl -X POST localhost:8000/auth/password-reset/request \
186
+ -H "Content-Type: application/json" \
187
+ -d '{"email": "ana@example.com"}'
188
+ ```
189
+
190
+ ```json
191
+ { "message": "If the email exists, we sent a link.", "reset_url": null }
192
+ ```
193
+
194
+ **Step 2 — set the new password.** The user opens the emailed link; the
195
+ front-end reads the `token` from the URL and sends it with the new
196
+ password. On success the password is replaced **and the user is logged
197
+ in** (a JWT pair comes back):
198
+
199
+ ```bash
200
+ curl -X POST localhost:8000/auth/password-reset/confirm \
201
+ -H "Content-Type: application/json" \
202
+ -d '{"token": "abc123…", "new_password": "new-strong-pass-12"}'
203
+ ```
204
+
205
+ ```json
206
+ {
207
+ "user_id": "7d8e4d5a-…",
208
+ "access_token": "eyJhbGciOi…",
209
+ "refresh_token": "eyJhbGciOi…",
210
+ "mfa_required": false,
211
+ "mfa_token": null
212
+ }
213
+ ```
214
+
215
+ !!! check "Errors you'll see"
216
+ - Unknown / already-used / expired token → **400**.
217
+ - `new_password` violates `AUTH_PASSWORD_MIN_LENGTH` / complexity → **422**.
218
+ - `request` **never** errors on a missing email — always **202**.
219
+
220
+ !!! note "Dev mode: link in the body (no SMTP)"
221
+ Without the `[email]` extra, or with `AUTH_RETURN_TOKEN_IN_RESPONSE=True`,
222
+ the `reset_url` comes back **in the `request` body** instead of by
223
+ email — you can drive the whole flow with no inbox. In production it
224
+ stays `null`.
225
+
226
+ ??? note "No front-end? Backend-rendered HTML pages (Mode E)"
227
+ With `AUTH_BACKEND_LINKS=True` the SDK mounts **GET/POST**
228
+ `/auth/password-reset/{token}`: the emailed link points at the
229
+ backend, which renders an HTML form, validates it and shows a
230
+ success/error page — no front-end route at all. See
231
+ [Five operating modes](#five-operating-modes) (Mode E).
232
+
233
+ ### Change your password (logged in)
234
+
235
+ Different from a reset: here the user **remembers** their password and
236
+ **is logged in**. No token, no email — they send the `access_token` in
237
+ the header and re-confirm their `current_password`:
177
238
 
178
- # ...user opens the link; the front extracts the token and confirms:
179
- await client.post("/auth/email-change/confirm", json={"token": token})
239
+ ```bash
240
+ curl -X POST localhost:8000/auth/password-change \
241
+ -H "Authorization: Bearer eyJhbGciOi…" \
242
+ -H "Content-Type: application/json" \
243
+ -d '{"current_password": "current-pass", "new_password": "new-strong-pass-12"}'
244
+ ```
245
+
246
+ Returns **204**; current tokens stay valid (this endpoint doesn't revoke
247
+ sessions). Wrong `current_password` → **401**.
248
+
249
+ !!! tip "Reset vs change — which is which?"
250
+ - **Forgot** the password, not logged in → **[Password recovery](#password-recovery)** (`password-reset/request` → `confirm`, prove with an emailed token).
251
+ - **Remembers** the password, logged in → **change password** (`password-change`, prove with the current password in the header).
252
+
253
+ ## Email change and recovery
254
+
255
+ The mirror of the password flow, but for the account **email** (v0.92.0+).
256
+ Three distinct cases — start at yours.
257
+
258
+ ### Change email (logged in)
259
+
260
+ The base case: the user **is logged in** and wants to change their own
261
+ email. They confirm `current_password` and supply `new_email`; a
262
+ confirmation link goes to the **new** address. The email only changes
263
+ once that link is confirmed.
264
+
265
+ ```bash
266
+ # Step 1 — request the change (authenticated). Always 202.
267
+ curl -X POST localhost:8000/auth/email-change/request \
268
+ -H "Authorization: Bearer eyJhbGciOi…" \
269
+ -H "Content-Type: application/json" \
270
+ -d '{"new_email": "new@example.com", "current_password": "current-pass"}'
271
+
272
+ # Step 2 — confirm (the front reads the token from the link sent to the new email).
273
+ curl -X POST localhost:8000/auth/email-change/confirm \
274
+ -H "Content-Type: application/json" \
275
+ -d '{"token": "abc123…"}'
276
+ ```
277
+
278
+ On confirmation, if `AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` (default) a
279
+ **security notice goes to the old address** — the banks/Google pattern,
280
+ so a hijacked account still alerts its owner.
281
+
282
+ !!! check "Errors"
283
+ - Wrong current password → **401**.
284
+ - `new_email` already in use (at request **or** confirm — a race) → **409**.
285
+ - Invalid / expired / used token → **400**.
286
+
287
+ ### Re-verify the current email
288
+
289
+ Re-sends a verification link to the **current address** — useful when the
290
+ activation email was lost. Authenticated, changes nothing; confirming the
291
+ link marks the account active.
292
+
293
+ ```bash
294
+ curl -X POST localhost:8000/auth/email-verify/request \
295
+ -H "Authorization: Bearer eyJhbGciOi…"
296
+ # then: POST /auth/email-verify/confirm {"token": "…"}
297
+ ```
298
+
299
+ ### Email recovery
300
+
301
+ The "I forgot / lost access to my email". An **unauthenticated** and
302
+ **opt-in** endpoint — only mounted with `AUTH_EMAIL_RECOVERY_ENABLED=True`.
303
+ The user proves identity with their **password** (and an **MFA code** when
304
+ TOTP is enrolled) and supplies the new address; the confirmation link goes
305
+ to the **new** email and reuses the same `email-change/confirm`.
306
+
307
+ ```bash
308
+ # Only exists if AUTH_EMAIL_RECOVERY_ENABLED=True. Always 202 (anti-enumeration).
309
+ curl -X POST localhost:8000/auth/email-recovery/request \
310
+ -H "Content-Type: application/json" \
311
+ -d '{
312
+ "email": "old@example.com",
313
+ "new_email": "new@example.com",
314
+ "current_password": "current-pass",
315
+ "mfa_code": "123456"
316
+ }'
317
+ # then: POST /auth/email-change/confirm {"token": "…"} (link went to the new email)
180
318
  ```
181
319
 
182
320
  !!! 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.
321
+ This endpoint lets whoever has the **password** move the account to
322
+ another email **without** accessing the old mailbox — an account-takeover
323
+ vector if the password leaked. Rules:
324
+
325
+ - **Opt-in**: off until `AUTH_EMAIL_RECOVERY_ENABLED=True`.
326
+ - Always a generic **202** for every soft failure (unknown email,
327
+ wrong password, missing/invalid `mfa_code`) — no account enumeration.
328
+ - When TOTP is enrolled, a valid `mfa_code` is required.
329
+ - Keep `AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` so the old email is always
330
+ alerted of the change.
190
331
 
191
332
  !!! info "Where the new email is stored"
192
333
  The pending address travels in the token's `payload` column
@@ -2,12 +2,32 @@
2
2
 
3
3
  Desde v0.31.0 o SDK fornece o ciclo completo de conta local — signup com email/senha, ativação por link, login com JWT pair, reset de senha — via `UserAuthService` + `make_auth_router`. **Endpoints prontos pra mount** (incluindo `POST /auth/refresh` desde v0.65.0), templates Jinja2 bundled, settings flags controlando se o link sai por e-mail ou no body da resposta, e quatro modos pré-pensados pra dev / staging / produção / CI.
4
4
 
5
+ !!! tip "Vá direto ao seu caso"
6
+ A tabela abaixo mapeia **o que o usuário quer fazer** → a seção e os
7
+ endpoints. Comece pelo seu caso; volte ao [setup](#setup-minimo) só
8
+ quando precisar ligar as peças.
9
+
10
+ | Quero… | Está logado? | Seção | Endpoints |
11
+ | --- | --- | --- | --- |
12
+ | Criar conta + ativar por e-mail | — | [Setup](#setup-minimo) | `signup` → `activate/{token}` |
13
+ | Entrar | — | [Endpoints](#endpoints) | `login` |
14
+ | **Esqueci minha senha** | ❌ não | **[Recuperação de senha](#recuperacao-de-senha)** | `password-reset/request` → `password-reset/confirm` |
15
+ | Trocar minha senha | ✅ sim | [Trocar senha logado](#trocar-a-senha-logado) | `password-change` |
16
+ | Trocar meu e-mail | ✅ sim | [Trocar e-mail](#trocar-e-mail-logado) | `email-change/request` → `email-change/confirm` |
17
+ | Re-verificar meu e-mail atual | ✅ sim | [Re-verificar e-mail](#re-verificar-o-e-mail-atual) | `email-verify/request` → `email-verify/confirm` |
18
+ | **Perdi acesso ao meu e-mail** | ❌ não | **[Recuperação de e-mail](#recuperacao-de-e-mail)** | `email-recovery/request` → `email-change/confirm` |
19
+ | Minha sessão expirou | — | [Refresh](#renovando-a-sessao-com-o-refresh-token) | `refresh` |
20
+
21
+ **Os dois "esqueci"**: senha perdida → [Recuperação de senha](#recuperacao-de-senha); caixa de e-mail perdida → [Recuperação de e-mail](#recuperacao-de-e-mail).
22
+
5
23
  ## Conteúdo da receita
6
24
 
7
25
  1. **[Setup mínimo](#setup-minimo)** — instalação dos extras + wiring de quatro objetos (`AsyncDatabaseManager`, `EmailUtils`, `UserAuthService`, `make_auth_router`).
8
26
  2. **[UserTokenModel concreto](#usertokenmodel-concreto)** — `BaseUserTokenModel` é abstrato, projeto cria a tabela final.
9
- 3. **[Endpoints](#endpoints)** — tabela dos 5 endpoints + payload + comportamento.
10
- 4. **[Settings — variáveis de ambiente](#settings-variaveis-de-ambiente)** — env vars em **seis grupos** (JWT, política de senha, fluxo de e-mail, TTL, URLs/templates, páginas backend) — cada uma em tabela tipada, não num blob.
27
+ 3. **[Endpoints](#endpoints)** — tabela de todos os endpoints + payload + comportamento.
28
+ 4. **[Recuperação de senha](#recuperacao-de-senha)** — o fluxo "esqueci a senha", passo a passo, mais trocar a senha logado.
29
+ 5. **[Troca e recuperação de e-mail](#troca-e-recuperacao-de-e-mail)** — trocar e-mail logado, re-verificar, e recuperar quando a caixa se perdeu.
30
+ 6. **[Settings — variáveis de ambiente](#settings-variaveis-de-ambiente)** — env vars em **grupos** (JWT, política de senha, fluxo de e-mail, TTL, URLs/templates, páginas backend) — cada uma em tabela tipada, não num blob.
11
31
  5. **[Anatomia de um e-mail: como link, template e URL se encaixam](#anatomia-de-um-e-mail)** — desambigua os três conceitos que mais confundem.
12
32
  6. **[Cinco modos de operação](#cinco-modos-de-operacao)** — produção, dev com SMTP local (Mailhog / smtp4dev), dev sem SMTP, CI sem ativação e **backend-only** (links e páginas servidas direto pelo backend).
13
33
  7. **[Mailhog vs smtp4dev — qual escolher pra dev local](#mailhog-vs-smtp4dev)** — comparativo + receitas docker-compose copy-paste.
@@ -149,42 +169,163 @@ uv run tempest db upgrade
149
169
  nem token de reset. Retorna **204** e os tokens atuais continuam
150
170
  válidos.
151
171
 
152
- ## Troca, verificação e recuperação de e-mail (v0.92.0+)
172
+ ## Recuperação de senha
153
173
 
154
- Espelha o fluxo de senha, mas pro **e-mail** da conta. Três cenários:
174
+ O clássico "esqueci minha senha". O usuário **não está logado** e prova
175
+ identidade com um **token de uso único** que chega por e-mail. São dois
176
+ passos.
155
177
 
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.
178
+ ### Caso base (SPA / JSON)
167
179
 
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)
180
+ **Passo 1 — pedir o link.** O usuário digita o e-mail; o backend sempre
181
+ responde **202** com a mesma mensagem genérica (não vaza se o e-mail
182
+ existe):
183
+
184
+ ```bash
185
+ curl -X POST localhost:8000/auth/password-reset/request \
186
+ -H "Content-Type: application/json" \
187
+ -d '{"email": "ana@example.com"}'
188
+ ```
189
+
190
+ ```json
191
+ { "message": "Se o e-mail existir, enviamos um link.", "reset_url": null }
192
+ ```
193
+
194
+ **Passo 2 — trocar a senha.** O usuário abre o link do e-mail; o
195
+ front-end lê o `token` da URL e o envia com a nova senha. Em caso de
196
+ sucesso a senha é trocada **e o usuário já sai logado** (vem um JWT pair):
197
+
198
+ ```bash
199
+ curl -X POST localhost:8000/auth/password-reset/confirm \
200
+ -H "Content-Type: application/json" \
201
+ -d '{"token": "abc123…", "new_password": "nova-senha-forte-12"}'
202
+ ```
203
+
204
+ ```json
205
+ {
206
+ "user_id": "7d8e4d5a-…",
207
+ "access_token": "eyJhbGciOi…",
208
+ "refresh_token": "eyJhbGciOi…",
209
+ "mfa_required": false,
210
+ "mfa_token": null
211
+ }
212
+ ```
213
+
214
+ !!! check "Erros que você vai ver"
215
+ - Token desconhecido / já usado / expirado → **400**.
216
+ - `new_password` viola `AUTH_PASSWORD_MIN_LENGTH` / complexidade → **422**.
217
+ - `request` **nunca** erra por e-mail inexistente — sempre **202**.
218
+
219
+ !!! note "Modo dev: link no body (sem SMTP)"
220
+ Sem o extra `[email]`, ou com `AUTH_RETURN_TOKEN_IN_RESPONSE=True`, o
221
+ `reset_url` volta **no corpo** do `request` em vez de ir por e-mail —
222
+ você dispara o fluxo inteiro sem inbox. Em produção ele fica `null`.
223
+
224
+ ??? note "Sem front-end? Páginas HTML pelo backend (Modo E)"
225
+ Com `AUTH_BACKEND_LINKS=True` o SDK monta **GET/POST**
226
+ `/auth/password-reset/{token}`: o link do e-mail aponta pro backend,
227
+ que renderiza um formulário HTML, valida e mostra uma página de
228
+ sucesso/erro — sem nenhuma rota no front-end. Veja
229
+ [Cinco modos de operação](#cinco-modos-de-operacao) (Modo E).
230
+
231
+ ### Trocar a senha (logado)
232
+
233
+ Diferente do reset: aqui o usuário **lembra** a senha e **está logado**.
234
+ Não há token nem e-mail — ele manda o `access_token` no header e
235
+ reconfirma a `current_password`:
176
236
 
177
- # ...usuário abre o link; o front extrai o token e confirma:
178
- await client.post("/auth/email-change/confirm", json={"token": token})
237
+ ```bash
238
+ curl -X POST localhost:8000/auth/password-change \
239
+ -H "Authorization: Bearer eyJhbGciOi…" \
240
+ -H "Content-Type: application/json" \
241
+ -d '{"current_password": "senha-atual", "new_password": "nova-senha-forte-12"}'
242
+ ```
243
+
244
+ Retorna **204**; os tokens atuais continuam válidos (este endpoint não
245
+ revoga sessões). `current_password` errada → **401**.
246
+
247
+ !!! tip "Reset vs change — qual é qual?"
248
+ - **Esqueceu** a senha, não está logado → **[Recuperação de senha](#recuperacao-de-senha)** (`password-reset/request` → `confirm`, prova com token de e-mail).
249
+ - **Lembra** a senha, está logado → **trocar a senha** (`password-change`, prova com a senha atual no header).
250
+
251
+ ## Troca e recuperação de e-mail
252
+
253
+ O espelho do fluxo de senha, mas pro **e-mail** da conta (v0.92.0+). Três
254
+ cenários distintos — comece pelo seu.
255
+
256
+ ### Trocar e-mail (logado)
257
+
258
+ O caso base: o usuário **está logado** e quer mudar o próprio e-mail.
259
+ Confirma a `current_password` e informa o `new_email`; um link de
260
+ confirmação vai pro **novo** endereço. O e-mail só muda quando esse link
261
+ é confirmado.
262
+
263
+ ```bash
264
+ # Passo 1 — pedir a troca (autenticado). Sempre 202.
265
+ curl -X POST localhost:8000/auth/email-change/request \
266
+ -H "Authorization: Bearer eyJhbGciOi…" \
267
+ -H "Content-Type: application/json" \
268
+ -d '{"new_email": "nova@example.com", "current_password": "senha-atual"}'
269
+
270
+ # Passo 2 — confirmar (o front lê o token do link enviado ao novo e-mail).
271
+ curl -X POST localhost:8000/auth/email-change/confirm \
272
+ -H "Content-Type: application/json" \
273
+ -d '{"token": "abc123…"}'
274
+ ```
275
+
276
+ Ao confirmar, se `AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` (padrão) um **aviso
277
+ de segurança vai pro endereço antigo** — o padrão de bancos/Google, pra
278
+ uma conta sequestrada ainda alertar o dono.
279
+
280
+ !!! check "Erros"
281
+ - Senha atual errada → **401**.
282
+ - `new_email` já em uso (no pedido **ou** na confirmação — corrida) → **409**.
283
+ - Token inválido / expirado / usado → **400**.
284
+
285
+ ### Re-verificar o e-mail atual
286
+
287
+ Reenvia um link de verificação pro **endereço atual** — útil quando o
288
+ e-mail de ativação se perdeu. Autenticado, sem trocar nada; confirmar o
289
+ link marca a conta ativa.
290
+
291
+ ```bash
292
+ curl -X POST localhost:8000/auth/email-verify/request \
293
+ -H "Authorization: Bearer eyJhbGciOi…"
294
+ # depois: POST /auth/email-verify/confirm {"token": "…"}
295
+ ```
296
+
297
+ ### Recuperação de e-mail
298
+
299
+ O "esqueci / perdi acesso ao meu e-mail". Endpoint **não autenticado** e
300
+ **opt-in** — só é montado com `AUTH_EMAIL_RECOVERY_ENABLED=True`. O
301
+ usuário prova identidade com a **senha** (e um **código MFA** quando o
302
+ TOTP está inscrito) e informa o novo endereço; o link de confirmação vai
303
+ pro **novo** e-mail e reusa o mesmo `email-change/confirm`.
304
+
305
+ ```bash
306
+ # Só existe se AUTH_EMAIL_RECOVERY_ENABLED=True. Sempre 202 (anti-enumeração).
307
+ curl -X POST localhost:8000/auth/email-recovery/request \
308
+ -H "Content-Type: application/json" \
309
+ -d '{
310
+ "email": "antigo@example.com",
311
+ "new_email": "novo@example.com",
312
+ "current_password": "senha-atual",
313
+ "mfa_code": "123456"
314
+ }'
315
+ # depois: POST /auth/email-change/confirm {"token": "…"} (link foi pro novo e-mail)
179
316
  ```
180
317
 
181
318
  !!! 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. é 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.
319
+ Esse endpoint deixa quem tem a **senha** mover a conta pra outro
320
+ e-mail **sem** acessar a caixa antiga vetor de account takeover se a
321
+ senha vazou. Regras:
322
+
323
+ - **Opt-in**: fica desligado até `AUTH_EMAIL_RECOVERY_ENABLED=True`.
324
+ - Sempre **202** genérico pra toda falha leve (e-mail desconhecido,
325
+ senha errada, `mfa_code` faltando/errado) — não enumera contas.
326
+ - Se o TOTP estiver inscrito, exige um `mfa_code` válido.
327
+ - Mantenha `AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` pra o e-mail antigo
328
+ sempre ser avisado da troca.
188
329
 
189
330
  !!! info "Onde o novo e-mail fica guardado"
190
331
  O endereço pendente viaja na coluna `payload` do token