tempest-fastapi-sdk 0.90.0__tar.gz → 0.91.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 (494) hide show
  1. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/CHANGELOG.md +46 -0
  2. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/CLAUDE.md +11 -4
  3. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/PKG-INFO +9 -6
  4. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/README.md +8 -5
  5. tempest_fastapi_sdk-0.91.0/docs/recipes/sse.en.md +390 -0
  6. tempest_fastapi_sdk-0.91.0/docs/recipes/sse.md +390 -0
  7. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/pyproject.toml +1 -1
  8. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/__init__.py +3 -1
  9. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/dependencies/auth.py +38 -7
  10. tempest_fastapi_sdk-0.91.0/tempest_fastapi_sdk/sse/__init__.py +23 -0
  11. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sse/broker.py +53 -2
  12. tempest_fastapi_sdk-0.91.0/tempest_fastapi_sdk/sse/event_stream.py +368 -0
  13. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_jwt_dependency.py +75 -0
  14. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/sse/test_broker.py +35 -0
  15. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/sse/test_event_stream.py +98 -0
  16. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/uv.lock +1 -1
  17. tempest_fastapi_sdk-0.90.0/docs/recipes/sse.en.md +0 -226
  18. tempest_fastapi_sdk-0.90.0/docs/recipes/sse.md +0 -226
  19. tempest_fastapi_sdk-0.90.0/tempest_fastapi_sdk/sse/__init__.py +0 -15
  20. tempest_fastapi_sdk-0.90.0/tempest_fastapi_sdk/sse/event_stream.py +0 -205
  21. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/.github/workflows/ci.yml +0 -0
  22. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/.github/workflows/docs.yml +0 -0
  23. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/.github/workflows/release-pypi.yml +0 -0
  24. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/.gitignore +0 -0
  25. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/.python-version +0 -0
  26. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/Makefile +0 -0
  27. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/architecture.en.md +0 -0
  28. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/architecture.md +0 -0
  29. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/changelog.en.md +0 -0
  30. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/changelog.md +0 -0
  31. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/contributing.en.md +0 -0
  32. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/contributing.md +0 -0
  33. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/index.en.md +0 -0
  34. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/index.md +0 -0
  35. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/installation.en.md +0 -0
  36. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/installation.md +0 -0
  37. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/index.en.md +0 -0
  38. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/index.md +0 -0
  39. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/api.en.md +0 -0
  40. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/api.md +0 -0
  41. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/business-rules.en.md +0 -0
  42. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/business-rules.md +0 -0
  43. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/domain.en.md +0 -0
  44. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/domain.md +0 -0
  45. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/flows.en.md +0 -0
  46. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/flows.md +0 -0
  47. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/index.en.md +0 -0
  48. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/learning/marketplace/index.md +0 -0
  49. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/migration.en.md +0 -0
  50. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/migration.md +0 -0
  51. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/admin.en.md +0 -0
  52. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/admin.md +0 -0
  53. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/audit-trail.en.md +0 -0
  54. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/audit-trail.md +0 -0
  55. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/auth-flow.en.md +0 -0
  56. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/auth-flow.md +0 -0
  57. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/br-helpers.en.md +0 -0
  58. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/br-helpers.md +0 -0
  59. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/cache.en.md +0 -0
  60. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/cache.md +0 -0
  61. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/cli.en.md +0 -0
  62. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/cli.md +0 -0
  63. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/database.en.md +0 -0
  64. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/database.md +0 -0
  65. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/deploy-safety.en.md +0 -0
  66. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/deploy-safety.md +0 -0
  67. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/downloads.en.md +0 -0
  68. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/downloads.md +0 -0
  69. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/email.en.md +0 -0
  70. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/email.md +0 -0
  71. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/feature-flags.en.md +0 -0
  72. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/feature-flags.md +0 -0
  73. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/fields.en.md +0 -0
  74. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/fields.md +0 -0
  75. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/file-store.en.md +0 -0
  76. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/file-store.md +0 -0
  77. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/http-client.en.md +0 -0
  78. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/http-client.md +0 -0
  79. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/http.en.md +0 -0
  80. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/http.md +0 -0
  81. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/idempotency.en.md +0 -0
  82. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/idempotency.md +0 -0
  83. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/index.en.md +0 -0
  84. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/index.md +0 -0
  85. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/logging.en.md +0 -0
  86. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/logging.md +0 -0
  87. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/metrics.en.md +0 -0
  88. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/metrics.md +0 -0
  89. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/mfa.en.md +0 -0
  90. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/mfa.md +0 -0
  91. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/multi-tenant.en.md +0 -0
  92. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/multi-tenant.md +0 -0
  93. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/observability.en.md +0 -0
  94. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/observability.md +0 -0
  95. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/offline-sync.en.md +0 -0
  96. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/offline-sync.md +0 -0
  97. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/outbox.en.md +0 -0
  98. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/outbox.md +0 -0
  99. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/queue-tasks.en.md +0 -0
  100. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/queue-tasks.md +0 -0
  101. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/realtime.en.md +0 -0
  102. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/realtime.md +0 -0
  103. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/refresh-tokens.en.md +0 -0
  104. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/refresh-tokens.md +0 -0
  105. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/security.en.md +0 -0
  106. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/security.md +0 -0
  107. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/sessions.en.md +0 -0
  108. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/sessions.md +0 -0
  109. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/storage.en.md +0 -0
  110. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/storage.md +0 -0
  111. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/stored-files.en.md +0 -0
  112. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/stored-files.md +0 -0
  113. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/testing.en.md +0 -0
  114. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/testing.md +0 -0
  115. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/typing.en.md +0 -0
  116. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/typing.md +0 -0
  117. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/uploads.en.md +0 -0
  118. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/uploads.md +0 -0
  119. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/utilities.en.md +0 -0
  120. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/utilities.md +0 -0
  121. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/vision.en.md +0 -0
  122. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/vision.md +0 -0
  123. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/webpush.en.md +0 -0
  124. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/webpush.md +0 -0
  125. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/websocket.en.md +0 -0
  126. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/recipes/websocket.md +0 -0
  127. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/reference.en.md +0 -0
  128. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/reference.md +0 -0
  129. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/roadmap.en.md +0 -0
  130. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/roadmap.md +0 -0
  131. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/ssr.en.md +0 -0
  132. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/ssr.md +0 -0
  133. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/tutorial.en.md +0 -0
  134. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/docs/tutorial.md +0 -0
  135. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/mkdocs.yml +0 -0
  136. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/mkdocs_hooks/llmstxt.py +0 -0
  137. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/scripts/extract_recipe.py +0 -0
  138. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
  139. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/actions.py +0 -0
  140. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
  141. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/config.py +0 -0
  142. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/discovery.py +0 -0
  143. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
  144. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/router.py +0 -0
  145. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/session.py +0 -0
  146. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/site.py +0 -0
  147. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
  148. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
  149. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
  150. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
  151. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
  152. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
  153. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
  154. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
  155. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
  156. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/admin/theme.py +0 -0
  157. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
  158. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
  159. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
  160. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
  161. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
  162. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
  163. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
  164. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
  165. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
  166. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
  167. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
  168. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
  169. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
  170. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
  171. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
  172. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
  173. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
  174. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
  175. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/server.py +0 -0
  176. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/static.py +0 -0
  177. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
  178. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
  179. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/__init__.py +0 -0
  180. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
  181. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/locale.py +0 -0
  182. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
  183. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/router.py +0 -0
  184. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
  185. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/service.py +0 -0
  186. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
  187. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
  188. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
  189. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
  190. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
  191. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
  192. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
  193. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
  194. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
  195. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
  196. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
  197. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
  198. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
  199. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
  200. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/auth/token_delivery.py +0 -0
  201. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
  202. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
  203. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
  204. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
  205. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
  206. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/Dockerfile.tmpl +0 -0
  207. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
  208. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/dockerignore.tmpl +0 -0
  209. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
  210. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
  211. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
  212. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
  213. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
  214. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
  215. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
  216. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
  217. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
  218. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
  219. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
  220. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
  221. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
  222. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
  223. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
  224. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
  225. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
  226. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
  227. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
  228. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
  229. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
  230. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
  231. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
  232. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
  233. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
  234. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/config.py +0 -0
  235. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/db.py +0 -0
  236. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
  237. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
  238. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
  239. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/main.py +0 -0
  240. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/new.py +0 -0
  241. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
  242. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
  243. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/cli/user.py +0 -0
  244. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
  245. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
  246. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
  247. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/core/context.py +0 -0
  248. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/core/enums.py +0 -0
  249. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/core/logging.py +0 -0
  250. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/core/typed.py +0 -0
  251. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
  252. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
  253. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
  254. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
  255. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/audit.py +0 -0
  256. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/backup.py +0 -0
  257. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/connection.py +0 -0
  258. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
  259. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
  260. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/model.py +0 -0
  261. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
  262. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/repository.py +0 -0
  263. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
  264. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
  265. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
  266. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
  267. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/user_refresh_token_model.py +0 -0
  268. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
  269. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/db/webpush_subscription_model.py +0 -0
  270. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
  271. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
  272. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
  273. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
  274. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
  275. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
  276. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
  277. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
  278. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
  279. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
  280. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
  281. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
  282. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
  283. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
  284. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/flags/service.py +0 -0
  285. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/py.typed +0 -0
  286. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
  287. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
  288. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
  289. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
  290. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
  291. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
  292. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
  293. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
  294. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
  295. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/services/base.py +0 -0
  296. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/services/file_mixin.py +0 -0
  297. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
  298. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
  299. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
  300. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
  301. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
  302. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
  303. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
  304. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
  305. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/settings/base.py +0 -0
  306. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/settings/mixins.py +0 -0
  307. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/ssr/__init__.py +0 -0
  308. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/ssr/_static/htmx.min.js +0 -0
  309. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/ssr/assets.py +0 -0
  310. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/ssr/page.py +0 -0
  311. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/ssr/response.py +0 -0
  312. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
  313. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
  314. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
  315. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
  316. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
  317. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
  318. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/testing/database.py +0 -0
  319. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
  320. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
  321. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
  322. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
  323. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
  324. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/download.py +0 -0
  325. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/email.py +0 -0
  326. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/fields.py +0 -0
  327. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/file_store.py +0 -0
  328. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
  329. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
  330. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
  331. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/log.py +0 -0
  332. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
  333. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
  334. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/password.py +0 -0
  335. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
  336. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
  337. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
  338. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
  339. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
  340. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/vision/__init__.py +0 -0
  341. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/vision/mapping.py +0 -0
  342. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/vision/schemas.py +0 -0
  343. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
  344. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
  345. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/webpush/router.py +0 -0
  346. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
  347. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/webpush/service.py +0 -0
  348. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
  349. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
  350. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
  351. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
  352. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/__init__.py +0 -0
  353. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/__init__.py +0 -0
  354. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_actions.py +0 -0
  355. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_auth.py +0 -0
  356. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_discovery.py +0 -0
  357. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_forms.py +0 -0
  358. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_logs_nav.py +0 -0
  359. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_mfa.py +0 -0
  360. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_rich_filters.py +0 -0
  361. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_router.py +0 -0
  362. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_site.py +0 -0
  363. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_theme.py +0 -0
  364. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_upload_field.py +0 -0
  365. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/admin/test_user_model.py +0 -0
  366. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/__init__.py +0 -0
  367. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_body_size.py +0 -0
  368. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_cookies.py +0 -0
  369. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_cors.py +0 -0
  370. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_csrf.py +0 -0
  371. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_dependencies_auth.py +0 -0
  372. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_graceful.py +0 -0
  373. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_handlers.py +0 -0
  374. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_health_router.py +0 -0
  375. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_idempotency.py +0 -0
  376. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_logs_router.py +0 -0
  377. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_oauth.py +0 -0
  378. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_prometheus.py +0 -0
  379. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_rate_limit.py +0 -0
  380. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_rate_limit_extras.py +0 -0
  381. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_request_id_middleware.py +0 -0
  382. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_role_dependency.py +0 -0
  383. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_server.py +0 -0
  384. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_static.py +0 -0
  385. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_tool_spec.py +0 -0
  386. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_tracing.py +0 -0
  387. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_webhooks.py +0 -0
  388. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/api/test_webhooks_rsa.py +0 -0
  389. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/__init__.py +0 -0
  390. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/test_cookie_delivery.py +0 -0
  391. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/test_guards.py +0 -0
  392. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/test_locale.py +0 -0
  393. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/test_mfa.py +0 -0
  394. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/test_refresh.py +0 -0
  395. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/test_refresh_db.py +0 -0
  396. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/auth/test_service.py +0 -0
  397. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cache/__init__.py +0 -0
  398. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cache/test_decorator.py +0 -0
  399. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cache/test_invalidation.py +0 -0
  400. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cache/test_redis_manager.py +0 -0
  401. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/__init__.py +0 -0
  402. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_config.py +0 -0
  403. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_db.py +0 -0
  404. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_db_seed.py +0 -0
  405. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_docker_compose.py +0 -0
  406. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_generate.py +0 -0
  407. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_lint_strictness.py +0 -0
  408. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_main.py +0 -0
  409. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_secrets.py +0 -0
  410. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/cli/test_user.py +0 -0
  411. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/conftest.py +0 -0
  412. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/controllers/__init__.py +0 -0
  413. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/controllers/test_base.py +0 -0
  414. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/core/__init__.py +0 -0
  415. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/core/test_context.py +0 -0
  416. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/core/test_enums.py +0 -0
  417. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/core/test_logging.py +0 -0
  418. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/core/test_typed.py +0 -0
  419. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/__init__.py +0 -0
  420. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_alembic_hooks.py +0 -0
  421. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_audit.py +0 -0
  422. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_backup.py +0 -0
  423. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_bulk_ops.py +0 -0
  424. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_connection.py +0 -0
  425. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_migrations.py +0 -0
  426. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_mixins.py +0 -0
  427. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_model.py +0 -0
  428. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_outbox.py +0 -0
  429. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_repository.py +0 -0
  430. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_safe_upgrade.py +0 -0
  431. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_slow_query.py +0 -0
  432. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/db/test_tenant.py +0 -0
  433. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/exceptions/__init__.py +0 -0
  434. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/exceptions/test_exceptions.py +0 -0
  435. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/exceptions/test_i18n.py +0 -0
  436. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/flags/__init__.py +0 -0
  437. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/flags/test_flags.py +0 -0
  438. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/queue/__init__.py +0 -0
  439. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/queue/test_manager.py +0 -0
  440. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/schemas/__init__.py +0 -0
  441. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/schemas/test_base.py +0 -0
  442. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/schemas/test_cursor_pagination.py +0 -0
  443. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/schemas/test_link_headers.py +0 -0
  444. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/schemas/test_pagination.py +0 -0
  445. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/schemas/test_response.py +0 -0
  446. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/services/__init__.py +0 -0
  447. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/services/test_base.py +0 -0
  448. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/services/test_file_mixin.py +0 -0
  449. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/sessions/__init__.py +0 -0
  450. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/sessions/test_sessions.py +0 -0
  451. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/settings/__init__.py +0 -0
  452. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/settings/test_base.py +0 -0
  453. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/settings/test_mixins.py +0 -0
  454. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/sse/__init__.py +0 -0
  455. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/ssr/__init__.py +0 -0
  456. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/ssr/test_integration.py +0 -0
  457. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/ssr/test_page.py +0 -0
  458. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/ssr/test_response.py +0 -0
  459. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/storage/__init__.py +0 -0
  460. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/storage/test_minio_client.py +0 -0
  461. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/tasks/__init__.py +0 -0
  462. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/tasks/test_manager.py +0 -0
  463. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/tasks/test_scheduler.py +0 -0
  464. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/testing/__init__.py +0 -0
  465. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/testing/test_database.py +0 -0
  466. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/__init__.py +0 -0
  467. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_client_ip.py +0 -0
  468. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_datetime.py +0 -0
  469. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_dict.py +0 -0
  470. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_download.py +0 -0
  471. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_email.py +0 -0
  472. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_fields.py +0 -0
  473. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_file_store.py +0 -0
  474. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_http_client.py +0 -0
  475. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_jwt.py +0 -0
  476. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_lazy_extras.py +0 -0
  477. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_locations.py +0 -0
  478. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_log.py +0 -0
  479. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_metrics.py +0 -0
  480. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_opaque_token.py +0 -0
  481. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_password.py +0 -0
  482. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_regex.py +0 -0
  483. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_storage_backends.py +0 -0
  484. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_throttle.py +0 -0
  485. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/utils/test_upload.py +0 -0
  486. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/vision/__init__.py +0 -0
  487. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/vision/test_vision.py +0 -0
  488. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/webpush/__init__.py +0 -0
  489. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/webpush/test_dispatcher.py +0 -0
  490. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/webpush/test_router.py +0 -0
  491. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/webpush/test_schemas.py +0 -0
  492. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/webpush/test_service.py +0 -0
  493. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/websockets/__init__.py +0 -0
  494. {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.91.0}/tests/websockets/test_hub_and_router.py +0 -0
@@ -5,6 +5,52 @@ 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.91.0] — 2026-07-05
9
+
10
+ ### Added
11
+
12
+ - **SSE backpressure — bounded queue + overflow policy.**
13
+ `EventStream` (and `SSEBroker`-created streams) now cap the buffered
14
+ events at `max_queue` (default `1000`) instead of growing without
15
+ limit when a client stalls. When the buffer fills, `overflow` decides
16
+ what gives:
17
+ - `"drop_oldest"` (default) — evict the stalest event, keep the
18
+ freshest data.
19
+ - `"drop_newest"` — discard the incoming event, keep the backlog.
20
+ - `"block"` — apply real backpressure (the producer waits for a slot).
21
+ `EventStream.dropped_events` counts events lost to overflow for
22
+ metrics / logs. `max_queue=0` restores the pre-0.91 unbounded
23
+ behavior. The `close()` sentinel is never dropped or blocked, so a
24
+ stream can always terminate. `SSEBroker(max_queue=..., overflow=...)`
25
+ applies the same policy to every stream it opens.
26
+ - **SSE lifecycle helpers — no more hand-rolled `try/finally`.**
27
+ - `sse_response(..., on_disconnect=...)` runs a cleanup callback
28
+ (awaited if a coroutine) when the client disconnects or the stream
29
+ ends — the one place guaranteed to fire — so a bound producer task
30
+ is cancelled or a channel unregistered without boilerplate.
31
+ - `EventStream.response(*, on_disconnect=..., status_code=...,
32
+ headers=...)` wraps `stream()` in an SSE response in one call.
33
+ - `SSEBroker.response(channel, ...)` bundles the whole per-connection
34
+ lifecycle: `register` + `sse_response` + `unregister`-on-disconnect.
35
+ This removes the leak-prone manual wrapper the recipe used to need.
36
+ - **JWT via query string for cookieless clients.**
37
+ `make_bearer_token_dependency` and `make_jwt_user_dependency` gained a
38
+ `query_param` argument (e.g. `query_param="access_token"`). Token
39
+ lookup order becomes header → cookie → query string. This unblocks
40
+ browser `EventSource` (SSE), whose constructor accepts neither headers
41
+ nor a body. Documented with a security warning: use short-lived access
42
+ tokens only, over TLS, and scrub the value from access logs. Prefer a
43
+ session cookie (`withCredentials`) whenever the client shares the
44
+ API's origin.
45
+ - **`OverflowPolicy`** is exported from `tempest_fastapi_sdk.sse` and the
46
+ package root.
47
+
48
+ ### Fixed
49
+
50
+ - `tempest_fastapi_sdk/sse/__init__.py` re-exports now use the explicit
51
+ `X as X` alias form required by the repo's re-export convention (was a
52
+ structural defect flagged by strict type-checkers).
53
+
8
54
  ## [0.90.0] — 2026-07-04
9
55
 
10
56
  ### Added
@@ -55,7 +55,9 @@ without the docs being green.
55
55
 
56
56
  The SDK currently covers (Sep 2025+, post-v0.31.x):
57
57
 
58
- - **Auth** — JWT/bearer/role/permission/X-Token deps, full
58
+ - **Auth** — JWT/bearer/role/permission/X-Token deps (JWT deps
59
+ read the token from header → cookie → query string via
60
+ `query_param=`, for cookieless `EventSource`/SSE clients), full
59
61
  bundled flow (`UserAuthService` + `make_auth_router` covering
60
62
  signup/activate/login/password-reset), `BaseUserModel` +
61
63
  `BaseUserTokenModel`, OAuth2/OIDC providers
@@ -88,9 +90,14 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
88
90
  - **Pagination** — offset + cursor.
89
91
  - **Settings mixins** — every `*Settings` carries
90
92
  `title`/`description`/`examples` on every field.
91
- - **SSE** — `EventStream`, `ServerSentEvent`, `sse_response`, and
92
- `SSEBroker` (per-channel fan-out; in-memory single-process, or
93
- multi-worker via an injected Redis pub/sub bridge — same call site).
93
+ - **SSE** — `EventStream` (bounded queue + `overflow` backpressure —
94
+ `drop_oldest`/`drop_newest`/`block`, `dropped_events` counter,
95
+ `max_queue=0` to disable), `ServerSentEvent`, `sse_response`
96
+ (`on_disconnect=` cleanup), `EventStream.response`, and `SSEBroker`
97
+ (per-channel fan-out; `SSEBroker.response(channel)` bundles
98
+ register + response + unregister-on-disconnect; in-memory
99
+ single-process, or multi-worker via an injected Redis pub/sub bridge
100
+ — same call site).
94
101
  - **Throttle** — `AttemptThrottle` (any `ThrottleBackend`, e.g.
95
102
  `redis.asyncio.Redis`; no in-memory backend bundled).
96
103
  - **Base CRUD layers** — `BaseService[Repo, Resp, UpdateT]` and
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tempest-fastapi-sdk
3
- Version: 0.90.0
3
+ Version: 0.91.0
4
4
  Summary: Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects.
5
5
  Project-URL: Homepage, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
6
6
  Project-URL: Repository, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
@@ -200,7 +200,7 @@ Via `pyproject.toml`:
200
200
 
201
201
  ```toml
202
202
  dependencies = [
203
- "tempest-fastapi-sdk>=0.90.0",
203
+ "tempest-fastapi-sdk>=0.91.0",
204
204
  ]
205
205
  ```
206
206
 
@@ -258,7 +258,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
258
258
  | `tempest_fastapi_sdk.services` | `BaseService` |
259
259
  | `tempest_fastapi_sdk.core` | `configure_logging`, `JSONFormatter`, `get_request_id`/`set_request_id`/`clear_request_id`, `request_id_ctx`, `BaseStrEnum`, `BaseIntEnum`, `strict_types`/`typed`/`require_annotations` |
260
260
  | `tempest_fastapi_sdk.admin` *(extra: `[admin]`)* | `AdminSite`, `AdminModel`, `make_admin_router`, `AdminAuthBackend`, `UserModelAuthBackend`, `AdminAuthError` |
261
- | `tempest_fastapi_sdk.sse` | `EventStream`, `SSEBroker` (multi-worker fan-out via Redis), `ServerSentEvent`, `sse_response` |
261
+ | `tempest_fastapi_sdk.sse` | `EventStream` (bounded queue + `overflow` backpressure), `SSEBroker` (multi-worker fan-out via Redis, `.response()` lifecycle helper), `ServerSentEvent`, `sse_response` (`on_disconnect=` cleanup) |
262
262
  | `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
263
263
  | `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
264
264
  | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `make_web_push_router`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
@@ -2445,7 +2445,7 @@ import asyncio
2445
2445
 
2446
2446
  from fastapi import APIRouter
2447
2447
 
2448
- from tempest_fastapi_sdk import EventStream, sse_response
2448
+ from tempest_fastapi_sdk import EventStream
2449
2449
 
2450
2450
  router = APIRouter()
2451
2451
 
@@ -2460,8 +2460,9 @@ async def events() -> "StreamingResponse": # forward-declared by Starlette
2460
2460
  await asyncio.sleep(1)
2461
2461
  await stream.close()
2462
2462
 
2463
- asyncio.create_task(producer())
2464
- return sse_response(stream.stream())
2463
+ task = asyncio.create_task(producer())
2464
+ # on_disconnect cancels the producer when the client drops — no leak.
2465
+ return stream.response(on_disconnect=task.cancel)
2465
2466
  ```
2466
2467
 
2467
2468
  Browser side:
@@ -2473,6 +2474,8 @@ es.addEventListener("counter", (e) => console.log("got", JSON.parse(e.data)));
2473
2474
 
2474
2475
  `heartbeat_seconds` emits a `: keepalive` SSE comment when idle so load-balancers don't close long-lived connections. `ServerSentEvent.data` accepts strings, bytes or any JSON-serializable Python object — non-strings are JSON-encoded automatically. Pass `retry=` to hint the browser at the reconnect delay (milliseconds).
2475
2476
 
2477
+ The queue is **bounded** (`max_queue`, default `1000`): a slow client can't grow memory without limit. `overflow` picks the eviction policy — `"drop_oldest"` (default), `"drop_newest"`, or `"block"` (real backpressure); `EventStream.dropped_events` counts the discards. For broadcast, `SSEBroker.response(channel)` bundles `register` + `sse_response` + `unregister`-on-disconnect in one call. Authenticating an `EventSource` (which can't send an `Authorization` header): prefer a session cookie (`make_jwt_user_dependency(..., cookie_name="access_token")` + `withCredentials`); for cookieless clients pass a short-lived access token in the query string with `query_param="access_token"` (over TLS, scrubbed from logs). See the [SSE recipe](https://mauriciobenjamin700.github.io/tempest-fastapi-sdk/recipes/sse/) for the full guide.
2478
+
2476
2479
  ### Web Push notifications recipe
2477
2480
 
2478
2481
  `WebPushDispatcher` wraps the synchronous `pywebpush` library in `asyncio.to_thread` and surfaces the two errors the application cares about: `WebPushGoneError` (HTTP 404/410 — delete the subscription) and `WebPushError` (everything else). Install with `[webpush]`.
@@ -91,7 +91,7 @@ Via `pyproject.toml`:
91
91
 
92
92
  ```toml
93
93
  dependencies = [
94
- "tempest-fastapi-sdk>=0.90.0",
94
+ "tempest-fastapi-sdk>=0.91.0",
95
95
  ]
96
96
  ```
97
97
 
@@ -149,7 +149,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
149
149
  | `tempest_fastapi_sdk.services` | `BaseService` |
150
150
  | `tempest_fastapi_sdk.core` | `configure_logging`, `JSONFormatter`, `get_request_id`/`set_request_id`/`clear_request_id`, `request_id_ctx`, `BaseStrEnum`, `BaseIntEnum`, `strict_types`/`typed`/`require_annotations` |
151
151
  | `tempest_fastapi_sdk.admin` *(extra: `[admin]`)* | `AdminSite`, `AdminModel`, `make_admin_router`, `AdminAuthBackend`, `UserModelAuthBackend`, `AdminAuthError` |
152
- | `tempest_fastapi_sdk.sse` | `EventStream`, `SSEBroker` (multi-worker fan-out via Redis), `ServerSentEvent`, `sse_response` |
152
+ | `tempest_fastapi_sdk.sse` | `EventStream` (bounded queue + `overflow` backpressure), `SSEBroker` (multi-worker fan-out via Redis, `.response()` lifecycle helper), `ServerSentEvent`, `sse_response` (`on_disconnect=` cleanup) |
153
153
  | `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
154
154
  | `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
155
155
  | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `make_web_push_router`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
@@ -2336,7 +2336,7 @@ import asyncio
2336
2336
 
2337
2337
  from fastapi import APIRouter
2338
2338
 
2339
- from tempest_fastapi_sdk import EventStream, sse_response
2339
+ from tempest_fastapi_sdk import EventStream
2340
2340
 
2341
2341
  router = APIRouter()
2342
2342
 
@@ -2351,8 +2351,9 @@ async def events() -> "StreamingResponse": # forward-declared by Starlette
2351
2351
  await asyncio.sleep(1)
2352
2352
  await stream.close()
2353
2353
 
2354
- asyncio.create_task(producer())
2355
- return sse_response(stream.stream())
2354
+ task = asyncio.create_task(producer())
2355
+ # on_disconnect cancels the producer when the client drops — no leak.
2356
+ return stream.response(on_disconnect=task.cancel)
2356
2357
  ```
2357
2358
 
2358
2359
  Browser side:
@@ -2364,6 +2365,8 @@ es.addEventListener("counter", (e) => console.log("got", JSON.parse(e.data)));
2364
2365
 
2365
2366
  `heartbeat_seconds` emits a `: keepalive` SSE comment when idle so load-balancers don't close long-lived connections. `ServerSentEvent.data` accepts strings, bytes or any JSON-serializable Python object — non-strings are JSON-encoded automatically. Pass `retry=` to hint the browser at the reconnect delay (milliseconds).
2366
2367
 
2368
+ The queue is **bounded** (`max_queue`, default `1000`): a slow client can't grow memory without limit. `overflow` picks the eviction policy — `"drop_oldest"` (default), `"drop_newest"`, or `"block"` (real backpressure); `EventStream.dropped_events` counts the discards. For broadcast, `SSEBroker.response(channel)` bundles `register` + `sse_response` + `unregister`-on-disconnect in one call. Authenticating an `EventSource` (which can't send an `Authorization` header): prefer a session cookie (`make_jwt_user_dependency(..., cookie_name="access_token")` + `withCredentials`); for cookieless clients pass a short-lived access token in the query string with `query_param="access_token"` (over TLS, scrubbed from logs). See the [SSE recipe](https://mauriciobenjamin700.github.io/tempest-fastapi-sdk/recipes/sse/) for the full guide.
2369
+
2367
2370
  ### Web Push notifications recipe
2368
2371
 
2369
2372
  `WebPushDispatcher` wraps the synchronous `pywebpush` library in `asyncio.to_thread` and surfaces the two errors the application cares about: `WebPushGoneError` (HTTP 404/410 — delete the subscription) and `WebPushError` (everything else). Install with `[webpush]`.
@@ -0,0 +1,390 @@
1
+ # Server-Sent Events (SSE)
2
+
3
+ SSE pushes data from the server to the browser over **one long-lived HTTP
4
+ connection**, no polling. It's the simplest path to "one-way real time":
5
+ a notification feed, a progress bar, a price ticker, live logs.
6
+
7
+ !!! info "SSE vs WebSocket vs Web Push"
8
+ - **SSE** — server → client, text only, auto-reconnects, runs over
9
+ plain HTTP. Use when the client only **receives**.
10
+ - **WebSocket** — bidirectional, binary, more complex. Use when the
11
+ client also **sends** often. See [WebSocket](websocket.md).
12
+ - **Web Push** — arrives with the **page closed** (Service Worker).
13
+ See [Web Push](webpush.md).
14
+
15
+ The SDK ships three pieces: `EventStream` (an in-memory async queue
16
+ feeding one connection), `ServerSentEvent` (encodes a frame in the spec
17
+ wire format) and `sse_response` (wraps the stream in a
18
+ `StreamingResponse` with the right headers — `Cache-Control: no-cache`,
19
+ `Connection: keep-alive`, `X-Accel-Buffering: no` to disable nginx
20
+ buffering).
21
+
22
+ !!! tip "New in v0.91"
23
+ - **Backpressure** — the `EventStream` queue is now **bounded**
24
+ (`max_queue`, default `1000`): a slow client can't grow memory
25
+ without limit. The `overflow` policy decides what gives. See
26
+ [Backpressure](#backpressure-bounded-queue).
27
+ - **Lifecycle without boilerplate** — `sse_response(..., on_disconnect=)`,
28
+ `EventStream.response(...)` and `SSEBroker.response(channel)` tear
29
+ down the producer / unregister the channel on their own when the
30
+ client drops.
31
+ - **Query-string auth** for cookieless clients (`EventSource`). See
32
+ [Authentication](#authentication-cookie-or-query-string).
33
+
34
+ ## One SSE endpoint
35
+
36
+ Create an `EventStream` per request, publish from a producer, and tie the
37
+ producer's lifecycle to the client connection — if the client drops, the
38
+ producer stops.
39
+
40
+ ```python
41
+ # src/api/routers/events.py
42
+ import asyncio
43
+
44
+ from fastapi import APIRouter
45
+ from starlette.responses import StreamingResponse
46
+
47
+ from tempest_fastapi_sdk import EventStream
48
+
49
+ router = APIRouter()
50
+
51
+
52
+ @router.get("/events")
53
+ async def events() -> StreamingResponse:
54
+ """Emit 3 SSE frames then close the stream."""
55
+ stream = EventStream(heartbeat_seconds=15.0)
56
+
57
+ async def producer() -> None:
58
+ try:
59
+ for n in range(1, 4):
60
+ await stream.publish({"n": n}, event="counter", id=str(n))
61
+ await asyncio.sleep(1)
62
+ finally:
63
+ await stream.close()
64
+
65
+ task = asyncio.create_task(producer())
66
+
67
+ # on_disconnect runs when the client drops OR the stream ends:
68
+ # that's where you cancel the producer so it doesn't leak.
69
+ return stream.response(on_disconnect=task.cancel)
70
+ ```
71
+
72
+ !!! warning "Always tie the producer to the connection"
73
+ SSE streams are long-lived. If the client disconnects mid-stream you
74
+ don't want the producer running forever. Pass `on_disconnect=` to
75
+ `EventStream.response` (or `sse_response`) — it runs in the response
76
+ generator's `finally`, the one place that fires on disconnect.
77
+
78
+ ??? note "Before v0.91: hand-rolled `try/finally`"
79
+ Up to v0.90 you wrapped `stream()` in an outer generator just to get
80
+ the `finally`. `on_disconnect=` replaces that boilerplate:
81
+
82
+ ```python
83
+ from collections.abc import AsyncIterator
84
+ from tempest_fastapi_sdk import sse_response
85
+
86
+ async def lifecycle_aware() -> AsyncIterator[bytes]:
87
+ try:
88
+ async for chunk in stream.stream():
89
+ yield chunk
90
+ finally:
91
+ task.cancel()
92
+
93
+ return sse_response(lifecycle_aware())
94
+ ```
95
+
96
+ ## Anatomy of an event
97
+
98
+ `publish()` takes the four spec fields:
99
+
100
+ ```python
101
+ await stream.publish(
102
+ {"orderId": "abc", "status": "paid"}, # data: auto-JSON
103
+ event="order_update", # event: front-end listener name
104
+ id="42", # id: becomes Last-Event-ID (resume)
105
+ retry=3000, # retry: reconnect hint (ms)
106
+ )
107
+ ```
108
+
109
+ | Field | What it does |
110
+ | --- | --- |
111
+ | `data` | Payload. String/bytes go raw; any object becomes JSON. |
112
+ | `event` | Event name — the front listens with `addEventListener(name)`. Without it, falls back to `"message"`. |
113
+ | `id` | Becomes `Last-Event-ID`; the browser resends it on reconnect so you can resume. |
114
+ | `retry` | Suggested reconnect delay (ms). |
115
+
116
+ `heartbeat_seconds` emits an SSE **comment** (`: keepalive`) while the
117
+ stream is idle so load-balancers don't cut the connection. Comments are
118
+ **invisible** to `EventSource` — they fire no listener, they just keep
119
+ the socket alive. `None` disables the heartbeat.
120
+
121
+ ## Backpressure (bounded queue)
122
+
123
+ If a client **stops reading** (backgrounded tab, bad network) but the
124
+ producer keeps publishing, the `EventStream` queue would grow forever — a
125
+ classic memory leak. So the queue is **bounded**: `max_queue` (default
126
+ `1000`) plus an `overflow` policy that decides what to do when it fills.
127
+
128
+ ```python
129
+ from tempest_fastapi_sdk import EventStream
130
+
131
+ # Live ticker: a stale frame is worthless -> drop the oldest.
132
+ stream = EventStream(max_queue=500, overflow="drop_oldest")
133
+ ```
134
+
135
+ | `overflow` | When the queue fills | Use when |
136
+ | --- | --- | --- |
137
+ | `"drop_oldest"` (default) | Evict the **oldest** event | Live data: ticker, progress, telemetry — only the recent state matters. |
138
+ | `"drop_newest"` | Discard the **incoming** event | The start of the stream matters more than the end. |
139
+ | `"block"` | Hold `publish()` until a slot frees | Producer dedicated to **one** connection and losing an event is unacceptable. |
140
+
141
+ !!! danger "`block` can stall a shared producer"
142
+ With `overflow="block"`, a slow client **holds** `publish()`. If the
143
+ same producer feeds many clients (fan-out), one bad client stalls them
144
+ all. Only use `block` when the producer serves **one** connection.
145
+
146
+ The `close()` sentinel is **never** dropped or blocked — the stream always
147
+ terminates. `stream.dropped_events` counts how many events were lost to
148
+ overflow, so you can surface it in metrics/logs:
149
+
150
+ ```python
151
+ if stream.dropped_events:
152
+ logger.warning("Slow SSE client: %d events dropped", stream.dropped_events)
153
+ ```
154
+
155
+ !!! tip "Back to the old behavior"
156
+ `max_queue=0` disables the bound (unbounded queue, pre-0.91). Only do
157
+ this if you're sure the producer stops together with the connection.
158
+
159
+ ## Broadcast to many clients (`SSEBroker`)
160
+
161
+ `EventStream` is **one** connection. To send the same event to every
162
+ client of a channel (e.g. a user's devices, or a topic), the SDK ships
163
+ `SSEBroker` — a per-channel stream registry plus fan-out. The channel is
164
+ any string (a user id, a room slug...).
165
+
166
+ ```python
167
+ # src/api/dependencies/resources.py
168
+ from tempest_fastapi_sdk import SSEBroker
169
+
170
+ broker = SSEBroker() # singleton — keep on app.state and inject via Depends
171
+ ```
172
+
173
+ ```python
174
+ # src/api/routers/feed.py
175
+ from uuid import UUID
176
+
177
+ from fastapi import APIRouter, Depends
178
+ from starlette.responses import StreamingResponse
179
+
180
+ from tempest_fastapi_sdk import SSEBroker
181
+
182
+ router = APIRouter()
183
+
184
+
185
+ @router.get("/feed")
186
+ async def feed(
187
+ user_id: UUID = Depends(get_current_user_id),
188
+ broker: SSEBroker = Depends(get_broker),
189
+ ) -> StreamingResponse:
190
+ """Subscribe the client to its user's channel."""
191
+ # register + sse_response + unregister-on-disconnect, all in one call.
192
+ return broker.response(str(user_id))
193
+
194
+
195
+ # From anywhere (queue handler, another endpoint):
196
+ # await broker.publish(str(user_id), {"text": "New order"}, event="notice")
197
+ ```
198
+
199
+ !!! tip "`broker.response()` kills the stream leak"
200
+ `broker.response(channel)` does `register`, wraps it in `sse_response`
201
+ and wires an `on_disconnect` that calls `unregister` when the client
202
+ drops. No `try/finally` to forget — every disconnect cleans up its own
203
+ registration. `SSEBroker(max_queue=..., overflow=...)` applies the same
204
+ backpressure policy to every stream it opens.
205
+
206
+ ### Multi-worker: Redis bridge (ready, no extra code)
207
+
208
+ An in-memory `SSEBroker` lives in **one** worker — with `--workers N` a
209
+ `publish` only reaches the clients pinned to that process. Pass a Redis
210
+ client and the **same `broker`** publishes via Redis `PUBLISH`; a
211
+ background task (`run()`) `PSUBSCRIBE`-s and relays to **each** worker's
212
+ local streams. Same call site, now horizontal:
213
+
214
+ ```python
215
+ # src/api/app.py
216
+ import asyncio
217
+ from contextlib import asynccontextmanager
218
+
219
+ from fastapi import FastAPI
220
+ from redis.asyncio import Redis
221
+
222
+ from tempest_fastapi_sdk import SSEBroker
223
+
224
+ redis = Redis.from_url("redis://localhost:6379/0", decode_responses=True)
225
+ broker = SSEBroker(redis=redis, channel_prefix="sse")
226
+
227
+
228
+ @asynccontextmanager
229
+ async def lifespan(app: FastAPI):
230
+ task = asyncio.create_task(broker.run()) # subscribe Redis + fan out
231
+ try:
232
+ yield
233
+ finally:
234
+ await broker.aclose()
235
+ task.cancel()
236
+
237
+
238
+ app = FastAPI(lifespan=lifespan)
239
+ # broker.publish(...) on any worker -> reaches ALL workers
240
+ ```
241
+
242
+ !!! tip "Start simple, scale later"
243
+ Without Redis, `SSEBroker()` already covers a single process. When you
244
+ need multiple workers/hosts, just inject a Redis client and start
245
+ `run()` in the lifespan — no endpoint changes. `publish` becomes
246
+ cross-process for free.
247
+
248
+ ## Authentication (cookie or query string)
249
+
250
+ Here's the SSE gotcha: the browser's native `EventSource` **can't** send
251
+ a header. No `Authorization: Bearer` on the handshake. So there are two
252
+ ways to authenticate the stream.
253
+
254
+ ### Preferred: session cookie
255
+
256
+ If the front is on the **same origin** as the API, use an `HttpOnly`
257
+ cookie. The browser sends it on its own when you open with
258
+ `withCredentials`:
259
+
260
+ ```javascript
261
+ const es = new EventSource("/api/feed", { withCredentials: true });
262
+ ```
263
+
264
+ On the backend, the SDK already reads the token from the cookie — the
265
+ same seam as `make_auth_router`'s cookie delivery mode:
266
+
267
+ ```python
268
+ # src/api/dependencies/auth.py
269
+ from tempest_fastapi_sdk import JWTUtils, make_jwt_user_dependency
270
+
271
+ tokens = JWTUtils(secret=settings.JWT_SECRET)
272
+
273
+ current_user = make_jwt_user_dependency(
274
+ tokens,
275
+ load_user,
276
+ cookie_name="access_token", # <- EventSource + withCredentials
277
+ )
278
+ ```
279
+
280
+ !!! check "Why cookie is better"
281
+ The token stays out of the URL: no leak into access logs, browser
282
+ history or the `Referer` header. `HttpOnly` also keeps the token out
283
+ of JavaScript's reach (XSS defense). Prefer this path **whenever** the
284
+ origin is shared.
285
+
286
+ ### Cookieless alternative: token in the query string
287
+
288
+ Without a session cookie (front on a **different origin**, a mobile app
289
+ opening a raw `EventSource`, an environment where `withCredentials` isn't
290
+ an option), pass the **access token** in the query string. As of v0.91
291
+ the dependency accepts this via `query_param`:
292
+
293
+ ```python
294
+ # src/api/dependencies/auth.py
295
+ from tempest_fastapi_sdk import JWTUtils, make_jwt_user_dependency
296
+
297
+ tokens = JWTUtils(secret=settings.JWT_SECRET)
298
+
299
+ # Lookup order: header -> cookie -> query string.
300
+ current_user = make_jwt_user_dependency(
301
+ tokens,
302
+ load_user,
303
+ query_param="access_token", # <- ?access_token=<jwt>
304
+ )
305
+ ```
306
+
307
+ ```python
308
+ # src/api/routers/feed.py
309
+ from uuid import UUID
310
+
311
+ from fastapi import APIRouter, Depends
312
+ from starlette.responses import StreamingResponse
313
+
314
+ from tempest_fastapi_sdk import SSEBroker
315
+
316
+ router = APIRouter()
317
+
318
+
319
+ @router.get("/feed")
320
+ async def feed(
321
+ user: User = Depends(current_user), # resolves the JWT from the query
322
+ broker: SSEBroker = Depends(get_broker),
323
+ ) -> StreamingResponse:
324
+ """Authenticated stream without a cookie — token comes in the URL."""
325
+ return broker.response(str(user.id))
326
+ ```
327
+
328
+ On the front:
329
+
330
+ ```javascript
331
+ // The short-lived access token goes in the URL — never the refresh token.
332
+ const es = new EventSource(`/api/feed?access_token=${accessToken}`);
333
+ ```
334
+
335
+ !!! danger "Query strings leak — treat the token as disposable"
336
+ A token in the URL shows up in **access logs**, **history** and the
337
+ **`Referer`** header. Non-negotiable rules:
338
+
339
+ - **Short-lived access token** only (minutes). **Never** the refresh
340
+ token.
341
+ - Always over **TLS** (HTTPS).
342
+ - Strip the value from your proxy/server log format.
343
+ - Refresh through a normal endpoint (header/cookie), not the query.
344
+
345
+ !!! info "`query_param` also exists on the low-level dependency"
346
+ `make_bearer_token_dependency(tokens, query_param="access_token")`
347
+ returns just the decoded claims — use it when you build
348
+ `get_current_user` by hand. Same header → cookie → query order.
349
+
350
+ ## Aligned with tempest-react-sdk
351
+
352
+ `tempest-react-sdk`'s `createEventStream` / `useEventStream`
353
+ ([repo](https://github.com/mauriciobenjamin700/tempest-react-sdk))
354
+ consumes these endpoints with built-in exponential-backoff reconnect:
355
+
356
+ ```typescript
357
+ import { createEventStream } from "@mauriciobenjamin700/tempest-react-sdk";
358
+
359
+ const stream = createEventStream<{ text: string }>("/feed", {
360
+ withCredentials: true, // sends the auth cookie on the handshake
361
+ namedEvents: ["notice"], // <- matches publish(event="notice")
362
+ onMessage: (m) => console.log(m.event, m.data), // data already JSON-parsed
363
+ });
364
+ // stream.close() to tear down; stream.reconnect() to force a reconnect
365
+ ```
366
+
367
+ !!! tip "Heartbeat: comment vs a `ping` event"
368
+ `EventStream`'s heartbeat is a **comment** — `EventSource` ignores it,
369
+ so the react-sdk doesn't even need `heartbeatEvents`. If you prefer a
370
+ visible **named** heartbeat, publish
371
+ `await stream.publish("", event="ping")` and set
372
+ `heartbeatEvents: ["ping"]` on the front (its default).
373
+
374
+ Alignment points:
375
+
376
+ - `publish(event="x")` ↔ `namedEvents: ["x"]` + `onMessage`.
377
+ - non-string `data` becomes JSON ↔ the react default parser decodes JSON.
378
+ - `id=` ↔ `Last-Event-ID` resent on reconnect (resume where you left off).
379
+ - cookie auth ↔ `withCredentials: true`.
380
+
381
+ ## Recap
382
+
383
+ - `EventStream` (one per connection) + `sse_response` — an SSE endpoint with headers set.
384
+ - Tie the producer to the connection with `on_disconnect=` (on `EventStream.response`, `sse_response` or `broker.response`) — no hand-rolled `try/finally`.
385
+ - Queue is **bounded** (`max_queue`, default `1000`) + `overflow` (`drop_oldest`/`drop_newest`/`block`) prevents leaks from slow clients; `dropped_events` counts the discards.
386
+ - `publish(data, event=, id=, retry=)` covers the 4 spec fields; non-string `data` becomes JSON.
387
+ - Heartbeat is a comment (invisible to EventSource); `None` disables it.
388
+ - Broadcast = `SSEBroker`; `broker.response(channel)` does register + response + unregister; multi-worker = pass a Redis client + start `broker.run()` in the lifespan.
389
+ - Auth: **cookie** (`cookie_name` + `withCredentials`) on the same origin; **query string** (`query_param`, short-lived access token over TLS only) for cookieless clients.
390
+ - `tempest-react-sdk` `createEventStream`/`useEventStream` consumes with reconnect; `namedEvents` ↔ `publish(event=)`.