tempest-fastapi-sdk 0.78.0__tar.gz → 0.80.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 (458) hide show
  1. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/CHANGELOG.md +33 -0
  2. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/PKG-INFO +7 -7
  3. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/README.md +6 -6
  4. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/architecture.en.md +1 -1
  5. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/architecture.md +1 -1
  6. tempest_fastapi_sdk-0.80.0/docs/recipes/webpush.en.md +189 -0
  7. tempest_fastapi_sdk-0.80.0/docs/recipes/webpush.md +188 -0
  8. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/reference.md +2 -0
  9. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/pyproject.toml +1 -1
  10. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/__init__.py +7 -1
  11. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/controllers/base.py +14 -4
  12. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/__init__.py +8 -0
  13. tempest_fastapi_sdk-0.80.0/tempest_fastapi_sdk/db/webpush_subscription_model.py +126 -0
  14. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/services/base.py +16 -5
  15. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/webpush/__init__.py +2 -0
  16. tempest_fastapi_sdk-0.80.0/tempest_fastapi_sdk/webpush/service.py +220 -0
  17. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/controllers/test_base.py +2 -2
  18. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/services/test_base.py +1 -1
  19. tempest_fastapi_sdk-0.80.0/tests/webpush/test_service.py +135 -0
  20. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/uv.lock +1 -1
  21. tempest_fastapi_sdk-0.78.0/docs/recipes/webpush.en.md +0 -109
  22. tempest_fastapi_sdk-0.78.0/docs/recipes/webpush.md +0 -109
  23. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/.github/workflows/ci.yml +0 -0
  24. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/.github/workflows/docs.yml +0 -0
  25. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/.github/workflows/release-pypi.yml +0 -0
  26. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/.gitignore +0 -0
  27. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/.python-version +0 -0
  28. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/CLAUDE.md +0 -0
  29. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/Makefile +0 -0
  30. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/changelog.en.md +0 -0
  31. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/changelog.md +0 -0
  32. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/contributing.en.md +0 -0
  33. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/contributing.md +0 -0
  34. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/index.en.md +0 -0
  35. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/index.md +0 -0
  36. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/installation.en.md +0 -0
  37. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/installation.md +0 -0
  38. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/index.en.md +0 -0
  39. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/index.md +0 -0
  40. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/api.en.md +0 -0
  41. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/api.md +0 -0
  42. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/business-rules.en.md +0 -0
  43. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/business-rules.md +0 -0
  44. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/domain.en.md +0 -0
  45. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/domain.md +0 -0
  46. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/flows.en.md +0 -0
  47. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/flows.md +0 -0
  48. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/index.en.md +0 -0
  49. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/learning/marketplace/index.md +0 -0
  50. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/migration.en.md +0 -0
  51. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/migration.md +0 -0
  52. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/admin.en.md +0 -0
  53. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/admin.md +0 -0
  54. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/audit-trail.en.md +0 -0
  55. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/audit-trail.md +0 -0
  56. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/auth-flow.en.md +0 -0
  57. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/auth-flow.md +0 -0
  58. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/br-helpers.en.md +0 -0
  59. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/br-helpers.md +0 -0
  60. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/cache.en.md +0 -0
  61. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/cache.md +0 -0
  62. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/cli.en.md +0 -0
  63. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/cli.md +0 -0
  64. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/database.en.md +0 -0
  65. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/database.md +0 -0
  66. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/deploy-safety.en.md +0 -0
  67. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/deploy-safety.md +0 -0
  68. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/downloads.en.md +0 -0
  69. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/downloads.md +0 -0
  70. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/email.en.md +0 -0
  71. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/email.md +0 -0
  72. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/feature-flags.en.md +0 -0
  73. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/feature-flags.md +0 -0
  74. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/fields.en.md +0 -0
  75. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/fields.md +0 -0
  76. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/http-client.en.md +0 -0
  77. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/http-client.md +0 -0
  78. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/http.en.md +0 -0
  79. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/http.md +0 -0
  80. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/idempotency.en.md +0 -0
  81. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/idempotency.md +0 -0
  82. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/index.en.md +0 -0
  83. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/index.md +0 -0
  84. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/logging.en.md +0 -0
  85. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/logging.md +0 -0
  86. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/metrics.en.md +0 -0
  87. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/metrics.md +0 -0
  88. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/mfa.en.md +0 -0
  89. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/mfa.md +0 -0
  90. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/multi-tenant.en.md +0 -0
  91. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/multi-tenant.md +0 -0
  92. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/observability.en.md +0 -0
  93. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/observability.md +0 -0
  94. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/offline-sync.en.md +0 -0
  95. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/offline-sync.md +0 -0
  96. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/outbox.en.md +0 -0
  97. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/outbox.md +0 -0
  98. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/queue-tasks.en.md +0 -0
  99. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/queue-tasks.md +0 -0
  100. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/realtime.en.md +0 -0
  101. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/realtime.md +0 -0
  102. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/refresh-tokens.en.md +0 -0
  103. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/refresh-tokens.md +0 -0
  104. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/security.en.md +0 -0
  105. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/security.md +0 -0
  106. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/sessions.en.md +0 -0
  107. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/sessions.md +0 -0
  108. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/storage.en.md +0 -0
  109. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/storage.md +0 -0
  110. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/stored-files.en.md +0 -0
  111. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/stored-files.md +0 -0
  112. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/testing.en.md +0 -0
  113. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/testing.md +0 -0
  114. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/typing.en.md +0 -0
  115. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/typing.md +0 -0
  116. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/uploads.en.md +0 -0
  117. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/uploads.md +0 -0
  118. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/utilities.en.md +0 -0
  119. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/utilities.md +0 -0
  120. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/websocket.en.md +0 -0
  121. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/recipes/websocket.md +0 -0
  122. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/reference.en.md +0 -0
  123. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/roadmap.en.md +0 -0
  124. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/roadmap.md +0 -0
  125. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/tutorial.en.md +0 -0
  126. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/docs/tutorial.md +0 -0
  127. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/mkdocs.yml +0 -0
  128. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/mkdocs_hooks/llmstxt.py +0 -0
  129. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/scripts/extract_recipe.py +0 -0
  130. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
  131. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
  132. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/config.py +0 -0
  133. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/discovery.py +0 -0
  134. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
  135. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/router.py +0 -0
  136. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/session.py +0 -0
  137. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/site.py +0 -0
  138. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
  139. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
  140. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
  141. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
  142. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
  143. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
  144. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
  145. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
  146. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
  147. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/admin/theme.py +0 -0
  148. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
  149. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
  150. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
  151. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/dependencies/auth.py +0 -0
  152. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
  153. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
  154. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
  155. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
  156. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
  157. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
  158. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
  159. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
  160. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
  161. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
  162. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
  163. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
  164. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
  165. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
  166. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
  167. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/server.py +0 -0
  168. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/static.py +0 -0
  169. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
  170. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
  171. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/__init__.py +0 -0
  172. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
  173. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/locale.py +0 -0
  174. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
  175. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/router.py +0 -0
  176. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
  177. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/service.py +0 -0
  178. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
  179. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
  180. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
  181. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
  182. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
  183. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
  184. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
  185. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
  186. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
  187. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
  188. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
  189. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
  190. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
  191. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
  192. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
  193. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
  194. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
  195. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
  196. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
  197. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/Dockerfile.tmpl +0 -0
  198. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
  199. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/dockerignore.tmpl +0 -0
  200. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
  201. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
  202. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
  203. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
  204. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
  205. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
  206. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
  207. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
  208. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
  209. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
  210. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
  211. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
  212. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
  213. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
  214. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
  215. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
  216. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
  217. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
  218. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
  219. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
  220. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
  221. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
  222. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
  223. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
  224. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
  225. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/config.py +0 -0
  226. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/db.py +0 -0
  227. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
  228. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
  229. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
  230. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/main.py +0 -0
  231. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/new.py +0 -0
  232. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
  233. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
  234. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/cli/user.py +0 -0
  235. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
  236. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
  237. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/core/context.py +0 -0
  238. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/core/enums.py +0 -0
  239. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/core/logging.py +0 -0
  240. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/core/typed.py +0 -0
  241. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
  242. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
  243. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
  244. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/audit.py +0 -0
  245. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/backup.py +0 -0
  246. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/connection.py +0 -0
  247. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
  248. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
  249. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/model.py +0 -0
  250. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
  251. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/repository.py +0 -0
  252. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
  253. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
  254. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
  255. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
  256. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/user_refresh_token_model.py +0 -0
  257. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
  258. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
  259. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
  260. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
  261. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
  262. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
  263. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
  264. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
  265. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
  266. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
  267. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
  268. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
  269. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
  270. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
  271. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
  272. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/flags/service.py +0 -0
  273. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/py.typed +0 -0
  274. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
  275. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
  276. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
  277. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
  278. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
  279. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
  280. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
  281. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
  282. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
  283. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/services/file_mixin.py +0 -0
  284. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
  285. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
  286. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
  287. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
  288. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
  289. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
  290. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
  291. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
  292. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/settings/base.py +0 -0
  293. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/settings/mixins.py +0 -0
  294. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sse/__init__.py +0 -0
  295. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/sse/event_stream.py +0 -0
  296. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
  297. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
  298. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
  299. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
  300. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
  301. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
  302. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/testing/database.py +0 -0
  303. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
  304. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
  305. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
  306. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
  307. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
  308. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/download.py +0 -0
  309. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/email.py +0 -0
  310. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/fields.py +0 -0
  311. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
  312. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
  313. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
  314. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/log.py +0 -0
  315. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
  316. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
  317. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/password.py +0 -0
  318. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
  319. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
  320. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
  321. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
  322. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
  323. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
  324. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
  325. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
  326. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
  327. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
  328. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
  329. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/__init__.py +0 -0
  330. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/__init__.py +0 -0
  331. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_auth.py +0 -0
  332. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_discovery.py +0 -0
  333. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_forms.py +0 -0
  334. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_logs_nav.py +0 -0
  335. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_mfa.py +0 -0
  336. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_router.py +0 -0
  337. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_site.py +0 -0
  338. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_theme.py +0 -0
  339. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/admin/test_user_model.py +0 -0
  340. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/__init__.py +0 -0
  341. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_body_size.py +0 -0
  342. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_cookies.py +0 -0
  343. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_cors.py +0 -0
  344. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_csrf.py +0 -0
  345. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_dependencies_auth.py +0 -0
  346. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_graceful.py +0 -0
  347. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_handlers.py +0 -0
  348. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_health_router.py +0 -0
  349. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_idempotency.py +0 -0
  350. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_jwt_dependency.py +0 -0
  351. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_logs_router.py +0 -0
  352. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_oauth.py +0 -0
  353. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_prometheus.py +0 -0
  354. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_rate_limit.py +0 -0
  355. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_rate_limit_extras.py +0 -0
  356. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_request_id_middleware.py +0 -0
  357. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_role_dependency.py +0 -0
  358. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_server.py +0 -0
  359. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_static.py +0 -0
  360. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_tool_spec.py +0 -0
  361. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_tracing.py +0 -0
  362. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_webhooks.py +0 -0
  363. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/api/test_webhooks_rsa.py +0 -0
  364. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/auth/__init__.py +0 -0
  365. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/auth/test_guards.py +0 -0
  366. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/auth/test_locale.py +0 -0
  367. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/auth/test_mfa.py +0 -0
  368. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/auth/test_refresh.py +0 -0
  369. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/auth/test_refresh_db.py +0 -0
  370. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/auth/test_service.py +0 -0
  371. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cache/__init__.py +0 -0
  372. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cache/test_decorator.py +0 -0
  373. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cache/test_invalidation.py +0 -0
  374. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cache/test_redis_manager.py +0 -0
  375. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/__init__.py +0 -0
  376. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_config.py +0 -0
  377. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_db.py +0 -0
  378. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_db_seed.py +0 -0
  379. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_docker_compose.py +0 -0
  380. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_generate.py +0 -0
  381. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_lint_strictness.py +0 -0
  382. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_main.py +0 -0
  383. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_secrets.py +0 -0
  384. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/cli/test_user.py +0 -0
  385. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/conftest.py +0 -0
  386. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/controllers/__init__.py +0 -0
  387. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/core/__init__.py +0 -0
  388. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/core/test_context.py +0 -0
  389. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/core/test_enums.py +0 -0
  390. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/core/test_logging.py +0 -0
  391. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/core/test_typed.py +0 -0
  392. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/__init__.py +0 -0
  393. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_alembic_hooks.py +0 -0
  394. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_audit.py +0 -0
  395. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_backup.py +0 -0
  396. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_bulk_ops.py +0 -0
  397. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_connection.py +0 -0
  398. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_migrations.py +0 -0
  399. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_mixins.py +0 -0
  400. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_model.py +0 -0
  401. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_outbox.py +0 -0
  402. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_repository.py +0 -0
  403. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_safe_upgrade.py +0 -0
  404. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_slow_query.py +0 -0
  405. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/db/test_tenant.py +0 -0
  406. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/exceptions/__init__.py +0 -0
  407. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/exceptions/test_exceptions.py +0 -0
  408. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/exceptions/test_i18n.py +0 -0
  409. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/flags/__init__.py +0 -0
  410. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/flags/test_flags.py +0 -0
  411. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/queue/__init__.py +0 -0
  412. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/queue/test_manager.py +0 -0
  413. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/schemas/__init__.py +0 -0
  414. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/schemas/test_base.py +0 -0
  415. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/schemas/test_cursor_pagination.py +0 -0
  416. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/schemas/test_link_headers.py +0 -0
  417. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/schemas/test_pagination.py +0 -0
  418. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/schemas/test_response.py +0 -0
  419. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/services/__init__.py +0 -0
  420. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/services/test_file_mixin.py +0 -0
  421. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/sessions/__init__.py +0 -0
  422. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/sessions/test_sessions.py +0 -0
  423. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/settings/__init__.py +0 -0
  424. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/settings/test_base.py +0 -0
  425. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/settings/test_mixins.py +0 -0
  426. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/sse/__init__.py +0 -0
  427. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/sse/test_event_stream.py +0 -0
  428. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/storage/__init__.py +0 -0
  429. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/storage/test_minio_client.py +0 -0
  430. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/tasks/__init__.py +0 -0
  431. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/tasks/test_manager.py +0 -0
  432. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/tasks/test_scheduler.py +0 -0
  433. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/testing/__init__.py +0 -0
  434. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/testing/test_database.py +0 -0
  435. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/__init__.py +0 -0
  436. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_client_ip.py +0 -0
  437. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_datetime.py +0 -0
  438. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_dict.py +0 -0
  439. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_download.py +0 -0
  440. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_email.py +0 -0
  441. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_fields.py +0 -0
  442. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_http_client.py +0 -0
  443. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_jwt.py +0 -0
  444. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_lazy_extras.py +0 -0
  445. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_locations.py +0 -0
  446. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_log.py +0 -0
  447. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_metrics.py +0 -0
  448. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_opaque_token.py +0 -0
  449. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_password.py +0 -0
  450. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_regex.py +0 -0
  451. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_storage_backends.py +0 -0
  452. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_throttle.py +0 -0
  453. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/utils/test_upload.py +0 -0
  454. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/webpush/__init__.py +0 -0
  455. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/webpush/test_dispatcher.py +0 -0
  456. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/webpush/test_schemas.py +0 -0
  457. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/websockets/__init__.py +0 -0
  458. {tempest_fastapi_sdk-0.78.0 → tempest_fastapi_sdk-0.80.0}/tests/websockets/test_hub_and_router.py +0 -0
@@ -5,6 +5,39 @@ 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.80.0] — 2026-06-28
9
+
10
+ ### Added
11
+
12
+ - **Web Push subscription storage + service.** The webpush module gained
13
+ the missing persistence layer so apps no longer hand-roll it:
14
+ `BaseWebPushSubscriptionModel` (abstract table, one row per user device,
15
+ unique `endpoint`) + `make_web_push_subscription_model(user_table=...)`
16
+ factory, mirroring the `BaseUserTokenModel` pattern; and
17
+ `WebPushSubscriptionService` (generic over the concrete model) with
18
+ `subscribe` (idempotent upsert keyed by endpoint), `unsubscribe`,
19
+ `list_for_user`, `prune`, and `notify_user` — which fans a payload out
20
+ to every device and **auto-prunes the ones the push service reports as
21
+ gone (404/410)**. The wire shape matches `PushSubscription.toJSON()`,
22
+ so it lines up 1:1 with `tempest-react-sdk`'s `WebPushClient`
23
+ `onSubscribe` / `onUnsubscribe` callbacks. Exported from
24
+ `tempest_fastapi_sdk`, `tempest_fastapi_sdk.webpush` and
25
+ `tempest_fastapi_sdk.db`.
26
+
27
+ ## [0.79.0] — 2026-06-27
28
+
29
+ ### Changed
30
+
31
+ - **`BaseService` / `BaseController` `update` payload is now generically
32
+ typed.** Both classes gained an optional third type parameter
33
+ `UpdateT` (bound to `BaseSchema`, default `BaseSchema`) so `update`
34
+ accepts the project's own update schema instead of the bare
35
+ `BaseSchema`: `BaseService[Repo, Resp, MyUpdateSchema]` /
36
+ `BaseController[Service, Resp, MyUpdateSchema]`. The default keeps every
37
+ existing two-argument subclass working unchanged. Implemented with a
38
+ PEP 695/696 `TypeVar` default via `typing_extensions` (already present
39
+ through Pydantic).
40
+
8
41
  ## [0.78.0] — 2026-06-27
9
42
 
10
43
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tempest-fastapi-sdk
3
- Version: 0.78.0
3
+ Version: 0.80.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
@@ -210,7 +210,7 @@ Feature-rich helpers pull in third-party dependencies that you only need when yo
210
210
  | `[email]` | `aiosmtplib`, `jinja2` | `EmailUtils` + `render_template()` |
211
211
  | `[upload]` | `aiofiles`, `python-multipart` | `UploadUtils`, `LocalUploadStorage`, `MinIOUploadStorage` (when combined with `[minio]`) |
212
212
  | `[cache]` | `redis` | `AsyncRedisManager` |
213
- | `[webpush]` | `pywebpush`, `cryptography` | `WebPushDispatcher` |
213
+ | `[webpush]` | `pywebpush`, `cryptography` | `WebPushDispatcher`, `WebPushSubscriptionService`, `BaseWebPushSubscriptionModel` |
214
214
  | `[metrics]` | `psutil`, `nvidia-ml-py` | `MetricsUtils` |
215
215
  | `[queue]` | `faststream[rabbit]` | `AsyncBrokerManager` (FastStream) |
216
216
  | `[tasks]` | `taskiq`, `taskiq-aio-pika` | `AsyncTaskBrokerManager` (TaskIQ) |
@@ -241,7 +241,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
241
241
  | Module | Exports |
242
242
  | --- | --- |
243
243
  | `tempest_fastapi_sdk.schemas` | `BaseSchema`, `BaseResponseSchema`, `BasePaginationFilterSchema`, `BasePaginationSchema[T]`, `CursorPaginationFilterSchema`, `CursorPaginationSchema`, `LogEntrySchema`, `encode_cursor`, `decode_cursor`, `build_pagination_link_header` |
244
- | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `TenantScopedRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper` (+ `safe_upgrade`), `DestructiveMigrationError`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox`, audit trail (`BaseAuditLogModel`, `AuditAction`, `snapshot_model`, `diff_snapshots`, `BaseRepository.add_audited` / `update_audited` / `delete_audited`) |
244
+ | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `TenantScopedRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper` (+ `safe_upgrade`), `DestructiveMigrationError`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox`, audit trail (`BaseAuditLogModel`, `AuditAction`, `snapshot_model`, `diff_snapshots`, `BaseRepository.add_audited` / `update_audited` / `delete_audited`), `BaseWebPushSubscriptionModel` + `make_web_push_subscription_model` |
245
245
  | `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException`, i18n (`MessageCatalog`, `default_message_catalog`, `parse_accept_language`, `DEFAULT_LOCALE`) |
246
246
  | `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
247
247
  | `tempest_fastapi_sdk.api` | `register_exception_handlers`, `app_exception_handler`, `apply_cors`, `make_health_router`, `make_logs_router`, `make_prometheus_router`, `make_prometheus_registry`, `PrometheusMiddleware`, `LogSource`, `make_tool_spec_router`, `make_token_dependency`, `make_bearer_token_dependency`, `make_jwt_user_dependency`, `make_role_dependency`, `make_permission_dependency`, `require_x_token`, `run_server`, `RequestIDMiddleware`, `RateLimitMiddleware` (+ `RateLimitStore`/`MemoryRateLimitStore`/`RedisRateLimitStore`/`RateLimitResult` and `key_by_ip`/`key_by_jwt_subject`/`key_by_jwt_claim`/`key_by_header`), `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `GracefulShutdownMiddleware`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
@@ -253,7 +253,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
253
253
  | `tempest_fastapi_sdk.sse` | `EventStream`, `ServerSentEvent`, `sse_response` |
254
254
  | `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
255
255
  | `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
256
- | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
256
+ | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
257
257
  | `tempest_fastapi_sdk.queue` *(extra: `[queue]`)* | `AsyncBrokerManager` (FastStream lifecycle wrapper) |
258
258
  | `tempest_fastapi_sdk.storage` *(extra: `[minio]`)* | `AsyncMinIOClient`, `ObjectStat` — async MinIO/S3 facade |
259
259
  | `tempest_fastapi_sdk.utils.http_client` *(extra: `[http]`)* | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, `REQUEST_ID_HEADER` — typed httpx wrapper |
@@ -2126,7 +2126,7 @@ Each mixin owns its own env-var prefix — pick only the ones the service needs:
2126
2126
 
2127
2127
  `BaseService[RepositoryT, ResponseT]` and `BaseController[ServiceT, ResponseT]` are generic skeletons matching the SDK layering (router → controller → service → repository). They expose pass-through CRUD methods so simple endpoints can subclass them without overriding anything; you override only methods that need orchestration.
2128
2128
 
2129
- What you inherit by subclassing `BaseService[RepositoryT, ResponseT]`:
2129
+ `BaseService[RepositoryT, ResponseT]` accepts an optional third type argument — `BaseService[RepositoryT, ResponseT, UpdateT]` — that types the `update` payload (defaults to `BaseSchema`, so the two-argument form keeps working). What you inherit by subclassing it:
2130
2130
 
2131
2131
  | Method | Returns | Notes |
2132
2132
  | --- | --- | --- |
@@ -2136,7 +2136,7 @@ What you inherit by subclassing `BaseService[RepositoryT, ResponseT]`:
2136
2136
  | `paginate(filters=None, order_by=None, page=1, page_size=20, ascending=True)` | `dict` with mapped `items` + `total`/`page`/`size`/`pages`. | Offset pagination via `repository.paginate`. |
2137
2137
  | `count(filters=None)` | `int` | Pass-through to `repository.count`. |
2138
2138
  | `exists(filters)` | `bool` | Pass-through to `repository.exists`. |
2139
- | `update(id, data)` | `ResponseT` | Fetch by id, copy the fields present in `data` (a `BaseSchema`) onto the row, persist, map. `to_dict()` drops unset/`None`, so it serves PUT and PATCH alike. |
2139
+ | `update(id, data)` | `ResponseT` | Fetch by id, copy the fields present in `data` (typed `UpdateT`, the optional 3rd generic param — defaults to `BaseSchema`) onto the row, persist, map. `to_dict()` drops unset/`None`, so it serves PUT and PATCH alike. |
2140
2140
  | `delete(id)` | `None` | Hard delete via `repository.delete`. |
2141
2141
 
2142
2142
  `map_to_response` is `await`-ed when it returns a coroutine, so async mappers work transparently — no method override needed.
@@ -2149,7 +2149,7 @@ What you inherit by subclassing `BaseController[ServiceT, ResponseT]`:
2149
2149
  | `list(filters, order_by, ascending)` | `service.list` | Same. |
2150
2150
  | `paginate(filters, order_by, page, page_size, ascending)` | `service.paginate` | Same. |
2151
2151
  | `count(filters)` | `service.count` | Same. |
2152
- | `update(id, data)` | `service.update` | Same. |
2152
+ | `update(id, data)` | `service.update` | `data` typed by the optional 3rd generic param `UpdateT` (defaults to `BaseSchema`). |
2153
2153
  | `delete(id)` | `service.delete` | Same. |
2154
2154
 
2155
2155
  When a use case needs domain rules, override the inherited method in the service. When a use case needs to coordinate more than one service, override the inherited method (or add a new one) in the controller. The router never grows — it only depends on the controller.
@@ -107,7 +107,7 @@ Feature-rich helpers pull in third-party dependencies that you only need when yo
107
107
  | `[email]` | `aiosmtplib`, `jinja2` | `EmailUtils` + `render_template()` |
108
108
  | `[upload]` | `aiofiles`, `python-multipart` | `UploadUtils`, `LocalUploadStorage`, `MinIOUploadStorage` (when combined with `[minio]`) |
109
109
  | `[cache]` | `redis` | `AsyncRedisManager` |
110
- | `[webpush]` | `pywebpush`, `cryptography` | `WebPushDispatcher` |
110
+ | `[webpush]` | `pywebpush`, `cryptography` | `WebPushDispatcher`, `WebPushSubscriptionService`, `BaseWebPushSubscriptionModel` |
111
111
  | `[metrics]` | `psutil`, `nvidia-ml-py` | `MetricsUtils` |
112
112
  | `[queue]` | `faststream[rabbit]` | `AsyncBrokerManager` (FastStream) |
113
113
  | `[tasks]` | `taskiq`, `taskiq-aio-pika` | `AsyncTaskBrokerManager` (TaskIQ) |
@@ -138,7 +138,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
138
138
  | Module | Exports |
139
139
  | --- | --- |
140
140
  | `tempest_fastapi_sdk.schemas` | `BaseSchema`, `BaseResponseSchema`, `BasePaginationFilterSchema`, `BasePaginationSchema[T]`, `CursorPaginationFilterSchema`, `CursorPaginationSchema`, `LogEntrySchema`, `encode_cursor`, `decode_cursor`, `build_pagination_link_header` |
141
- | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `TenantScopedRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper` (+ `safe_upgrade`), `DestructiveMigrationError`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox`, audit trail (`BaseAuditLogModel`, `AuditAction`, `snapshot_model`, `diff_snapshots`, `BaseRepository.add_audited` / `update_audited` / `delete_audited`) |
141
+ | `tempest_fastapi_sdk.db` | `BaseModel`, `BaseUserModel`, `BaseUserTokenModel`, `BaseUserRecoveryCodeModel`, `make_user_recovery_code_model`, `UserTokenPurpose`, `BaseRepository[ModelType]`, `TenantScopedRepository[ModelType]`, `AsyncDatabaseManager`, `AlembicHelper` (+ `safe_upgrade`), `DestructiveMigrationError`, `NAMING_CONVENTION`, `AuditMixin`, `SoftDeleteMixin`, `MFAMixin`, `BASE_COLUMN_ORDER`, `reorder_base_columns_first`, `compose_hooks`, `SlowQueryLogger`, `BaseOutboxModel`, `OutboxRelay`, `OutboxStatus`, `BaseRepository.save_with_outbox`, audit trail (`BaseAuditLogModel`, `AuditAction`, `snapshot_model`, `diff_snapshots`, `BaseRepository.add_audited` / `update_audited` / `delete_audited`), `BaseWebPushSubscriptionModel` + `make_web_push_subscription_model` |
142
142
  | `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException`, i18n (`MessageCatalog`, `default_message_catalog`, `parse_accept_language`, `DEFAULT_LOCALE`) |
143
143
  | `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
144
144
  | `tempest_fastapi_sdk.api` | `register_exception_handlers`, `app_exception_handler`, `apply_cors`, `make_health_router`, `make_logs_router`, `make_prometheus_router`, `make_prometheus_registry`, `PrometheusMiddleware`, `LogSource`, `make_tool_spec_router`, `make_token_dependency`, `make_bearer_token_dependency`, `make_jwt_user_dependency`, `make_role_dependency`, `make_permission_dependency`, `require_x_token`, `run_server`, `RequestIDMiddleware`, `RateLimitMiddleware` (+ `RateLimitStore`/`MemoryRateLimitStore`/`RedisRateLimitStore`/`RateLimitResult` and `key_by_ip`/`key_by_jwt_subject`/`key_by_jwt_claim`/`key_by_header`), `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `GracefulShutdownMiddleware`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
@@ -150,7 +150,7 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
150
150
  | `tempest_fastapi_sdk.sse` | `EventStream`, `ServerSentEvent`, `sse_response` |
151
151
  | `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
152
152
  | `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
153
- | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
153
+ | `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
154
154
  | `tempest_fastapi_sdk.queue` *(extra: `[queue]`)* | `AsyncBrokerManager` (FastStream lifecycle wrapper) |
155
155
  | `tempest_fastapi_sdk.storage` *(extra: `[minio]`)* | `AsyncMinIOClient`, `ObjectStat` — async MinIO/S3 facade |
156
156
  | `tempest_fastapi_sdk.utils.http_client` *(extra: `[http]`)* | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, `REQUEST_ID_HEADER` — typed httpx wrapper |
@@ -2023,7 +2023,7 @@ Each mixin owns its own env-var prefix — pick only the ones the service needs:
2023
2023
 
2024
2024
  `BaseService[RepositoryT, ResponseT]` and `BaseController[ServiceT, ResponseT]` are generic skeletons matching the SDK layering (router → controller → service → repository). They expose pass-through CRUD methods so simple endpoints can subclass them without overriding anything; you override only methods that need orchestration.
2025
2025
 
2026
- What you inherit by subclassing `BaseService[RepositoryT, ResponseT]`:
2026
+ `BaseService[RepositoryT, ResponseT]` accepts an optional third type argument — `BaseService[RepositoryT, ResponseT, UpdateT]` — that types the `update` payload (defaults to `BaseSchema`, so the two-argument form keeps working). What you inherit by subclassing it:
2027
2027
 
2028
2028
  | Method | Returns | Notes |
2029
2029
  | --- | --- | --- |
@@ -2033,7 +2033,7 @@ What you inherit by subclassing `BaseService[RepositoryT, ResponseT]`:
2033
2033
  | `paginate(filters=None, order_by=None, page=1, page_size=20, ascending=True)` | `dict` with mapped `items` + `total`/`page`/`size`/`pages`. | Offset pagination via `repository.paginate`. |
2034
2034
  | `count(filters=None)` | `int` | Pass-through to `repository.count`. |
2035
2035
  | `exists(filters)` | `bool` | Pass-through to `repository.exists`. |
2036
- | `update(id, data)` | `ResponseT` | Fetch by id, copy the fields present in `data` (a `BaseSchema`) onto the row, persist, map. `to_dict()` drops unset/`None`, so it serves PUT and PATCH alike. |
2036
+ | `update(id, data)` | `ResponseT` | Fetch by id, copy the fields present in `data` (typed `UpdateT`, the optional 3rd generic param — defaults to `BaseSchema`) onto the row, persist, map. `to_dict()` drops unset/`None`, so it serves PUT and PATCH alike. |
2037
2037
  | `delete(id)` | `None` | Hard delete via `repository.delete`. |
2038
2038
 
2039
2039
  `map_to_response` is `await`-ed when it returns a coroutine, so async mappers work transparently — no method override needed.
@@ -2046,7 +2046,7 @@ What you inherit by subclassing `BaseController[ServiceT, ResponseT]`:
2046
2046
  | `list(filters, order_by, ascending)` | `service.list` | Same. |
2047
2047
  | `paginate(filters, order_by, page, page_size, ascending)` | `service.paginate` | Same. |
2048
2048
  | `count(filters)` | `service.count` | Same. |
2049
- | `update(id, data)` | `service.update` | Same. |
2049
+ | `update(id, data)` | `service.update` | `data` typed by the optional 3rd generic param `UpdateT` (defaults to `BaseSchema`). |
2050
2050
  | `delete(id)` | `service.delete` | Same. |
2051
2051
 
2052
2052
  When a use case needs domain rules, override the inherited method in the service. When a use case needs to coordinate more than one service, override the inherited method (or add a new one) in the controller. The router never grows — it only depends on the controller.
@@ -147,7 +147,7 @@ What you inherit by subclassing `BaseService[RepositoryT, ResponseT]`:
147
147
  | `paginate(filters=None, order_by=None, page=1, page_size=20, ascending=True)` | `dict` with mapped `items` + `total`/`page`/`page_size`/`pages`. | Offset pagination via `repository.paginate`. |
148
148
  | `count(filters=None)` | `int` | Pass-through to `repository.count`. |
149
149
  | `exists(filters)` | `bool` | Pass-through to `repository.exists`. |
150
- | `update(id, data)` | `ResponseT` | Fetch by id, copy the fields present in `data` (a `BaseSchema`) onto the row, persist, map. `to_dict()` drops unset/`None`, so it serves PUT and PATCH. |
150
+ | `update(id, data)` | `ResponseT` | Fetch by id, copy the fields present in `data` (typed by `UpdateT`, the optional 3rd generic param — defaults to `BaseSchema`) onto the row, persist, map. `to_dict()` drops unset/`None`, so it serves PUT and PATCH. |
151
151
  | `delete(id)` | `None` | Hard delete via `repository.delete`. |
152
152
 
153
153
  `map_to_response` is `await`-ed when it returns a coroutine, so async mappers work transparently — no method override needed.
@@ -147,7 +147,7 @@ O que você herda ao subclassear `BaseService[RepositoryT, ResponseT]`:
147
147
  | `paginate(filters=None, order_by=None, page=1, page_size=20, ascending=True)` | `dict` com `items` mapeados + `total`/`page`/`page_size`/`pages`. | Paginação por offset via `repository.paginate`. |
148
148
  | `count(filters=None)` | `int` | Pass-through para `repository.count`. |
149
149
  | `exists(filters)` | `bool` | Pass-through para `repository.exists`. |
150
- | `update(id, data)` | `ResponseT` | Busca por id, copia os campos presentes em `data` (um `BaseSchema`) na instância, persiste e mapeia. `to_dict()` descarta unset/`None`, então serve PUT e PATCH. |
150
+ | `update(id, data)` | `ResponseT` | Busca por id, copia os campos presentes em `data` (tipado por `UpdateT`, o 3º parâmetro genérico opcional — default `BaseSchema`) na instância, persiste e mapeia. `to_dict()` descarta unset/`None`, então serve PUT e PATCH. |
151
151
  | `delete(id)` | `None` | Hard delete via `repository.delete`. |
152
152
 
153
153
  `map_to_response` é aguardado com `await` quando retorna uma coroutine, então mappers async funcionam de forma transparente — sem precisar sobrescrever o método.
@@ -0,0 +1,189 @@
1
+ # Web Push
2
+
3
+ VAPID-signed Web Push notifications to browsers via `WebPushDispatcher`.
4
+ It wraps the synchronous `pywebpush` library in `asyncio.to_thread` and
5
+ surfaces the two errors the application actually handles:
6
+ `WebPushGoneError` (HTTP 404/410 — delete the subscription) and
7
+ `WebPushError` (any other failure). Requires the `[webpush]` extra
8
+ (`pywebpush` + `cryptography`).
9
+
10
+ ## VAPID configuration
11
+
12
+ `WebPushSettings` ships `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, and
13
+ `VAPID_SUBJECT`. The **public** key goes to the frontend (in
14
+ `pushManager.subscribe`); the **private** key signs each push on the
15
+ backend. The `sub` must be a `mailto:` or `https:` URI.
16
+
17
+ ```python
18
+ # src/services/notifications.py
19
+ from tempest_fastapi_sdk import WebPushDispatcher
20
+
21
+ from src.core.settings import settings
22
+
23
+
24
+ # settings.webpush_kwargs() -> vapid_private_key + vapid_subject + ttl_seconds
25
+ dispatcher = WebPushDispatcher(**settings.webpush_kwargs())
26
+ ```
27
+
28
+ ## Table + service (recommended)
29
+
30
+ To store the user's devices and deliver with automatic pruning, the SDK
31
+ ships the **base table** `BaseWebPushSubscriptionModel` (one row per
32
+ device, unique `endpoint`) and the **base service**
33
+ `WebPushSubscriptionService` (saves, removes and sends, pruning dead ones
34
+ itself). Like the auth pattern, the SDK provides the abstract row and the
35
+ project creates the concrete table with the FK to its `UserModel`:
36
+
37
+ ```python
38
+ # src/db/models/web_push_subscription.py
39
+ from sqlalchemy import ForeignKey
40
+ from sqlalchemy.orm import Mapped, mapped_column
41
+ from uuid import UUID
42
+
43
+ from tempest_fastapi_sdk import BaseWebPushSubscriptionModel
44
+
45
+
46
+ class WebPushSubscriptionModel(BaseWebPushSubscriptionModel):
47
+ """A user device's Web Push subscription."""
48
+
49
+ __tablename__ = "web_push_subscriptions"
50
+
51
+ user_id: Mapped[UUID] = mapped_column(
52
+ ForeignKey("users.id", ondelete="CASCADE"),
53
+ nullable=False,
54
+ index=True,
55
+ )
56
+ ```
57
+
58
+ Build the service from a `BaseRepository` over the table + the VAPID
59
+ dispatcher:
60
+
61
+ ```python
62
+ # src/api/dependencies/resources.py
63
+ from tempest_fastapi_sdk import BaseRepository, WebPushSubscriptionService
64
+
65
+ from src.core.settings import settings
66
+ from src.db.models import WebPushSubscriptionModel
67
+
68
+
69
+ def get_push_service(session: AsyncSession) -> WebPushSubscriptionService:
70
+ repo = BaseRepository(session, model=WebPushSubscriptionModel)
71
+ dispatcher = WebPushDispatcher(**settings.webpush_kwargs())
72
+ return WebPushSubscriptionService(repo, dispatcher)
73
+ ```
74
+
75
+ The service exposes:
76
+
77
+ | Method | What it does |
78
+ | --- | --- |
79
+ | `subscribe(user_id, subscription, *, user_agent=None)` | Persist the subscription, **idempotent by `endpoint`** — re-subscribe updates, never duplicates. |
80
+ | `unsubscribe(endpoint)` | Remove the subscription (no-op when absent). |
81
+ | `list_for_user(user_id)` | List the user's devices. |
82
+ | `notify_user(user_id, payload)` | Send to every device and **prune the dead ones** (404/410) before returning. Returns how many received it. |
83
+
84
+ ## Aligned with tempest-react-sdk
85
+
86
+ `tempest-react-sdk`'s [`WebPushClient`](https://github.com/mauriciobenjamin700/tempest-react-sdk)
87
+ calls `onSubscribe(subscription)` / `onUnsubscribe(subscription)` with the
88
+ raw `PushSubscription.toJSON()`. That JSON *is* the
89
+ `WebPushSubscriptionSchema` (it aliases `expiration_time` ↔
90
+ `expirationTime`), so the frontend hits these endpoints directly:
91
+
92
+ ```python
93
+ # src/api/routers/push.py
94
+ from fastapi import APIRouter, Depends, status
95
+
96
+ from tempest_fastapi_sdk import WebPushSubscriptionSchema, WebPushSubscriptionService
97
+
98
+ router = APIRouter(prefix="/api/push", tags=["push"])
99
+
100
+
101
+ @router.post("/subscribe", status_code=status.HTTP_201_CREATED)
102
+ async def subscribe(
103
+ subscription: WebPushSubscriptionSchema,
104
+ user: CurrentUser, # your auth dependency
105
+ service: WebPushSubscriptionService = Depends(get_push_service),
106
+ ) -> dict[str, str]:
107
+ """Receive the WebPushClient onSubscribe and persist the device."""
108
+ await service.subscribe(user.id, subscription)
109
+ return {"status": "subscribed"}
110
+
111
+
112
+ @router.post("/unsubscribe", status_code=status.HTTP_200_OK)
113
+ async def unsubscribe(
114
+ subscription: WebPushSubscriptionSchema,
115
+ service: WebPushSubscriptionService = Depends(get_push_service),
116
+ ) -> dict[str, str]:
117
+ """Receive the onUnsubscribe and remove the device."""
118
+ await service.unsubscribe(subscription.endpoint)
119
+ return {"status": "unsubscribed"}
120
+ ```
121
+
122
+ Notify a user (all devices, automatic pruning built in):
123
+
124
+ ```python
125
+ delivered: int = await service.notify_user(
126
+ user.id,
127
+ {"title": "Payment confirmed", "body": "Order approved."},
128
+ )
129
+ ```
130
+
131
+ ## Send a notification (dispatcher directly)
132
+
133
+ The `payload` accepts `WebPushPayloadSchema`, `dict`, `str`, or `bytes`
134
+ (models and dicts are JSON-encoded). Handle `WebPushGoneError` to prune
135
+ the dead subscription from your store.
136
+
137
+ ```python
138
+ from tempest_fastapi_sdk import (
139
+ WebPushGoneError,
140
+ WebPushPayloadSchema,
141
+ WebPushSubscriptionSchema,
142
+ )
143
+
144
+
145
+ async def notify_order_paid(
146
+ subscription: WebPushSubscriptionSchema,
147
+ order_id: str,
148
+ ) -> None:
149
+ payload = WebPushPayloadSchema(
150
+ title="Payment confirmed",
151
+ body=f"Order {order_id} approved.",
152
+ icon="/static/icons/order.png",
153
+ data={"orderId": order_id, "url": f"/orders/{order_id}"},
154
+ )
155
+ try:
156
+ await dispatcher.send(subscription, payload)
157
+ except WebPushGoneError:
158
+ await subscriptions_repo.delete_by_endpoint(subscription.endpoint)
159
+ ```
160
+
161
+ ## Broadcast with automatic pruning
162
+
163
+ `send_many()` fans out the same payload concurrently (`asyncio.gather`)
164
+ and **returns the dead endpoints** (404/410) for you to remove — other
165
+ failures are logged, not raised.
166
+
167
+ ```python
168
+ async def broadcast(
169
+ subs: list[WebPushSubscriptionSchema],
170
+ payload: WebPushPayloadSchema,
171
+ ) -> None:
172
+ gone: list[str] = await dispatcher.send_many(subs, payload)
173
+ if gone:
174
+ await subscriptions_repo.delete_by_endpoints(gone)
175
+ ```
176
+
177
+ !!! warning "Always prune dead subscriptions"
178
+ Subscriptions expire when the user changes device or revokes the
179
+ permission. Ignoring `WebPushGoneError` / the `send_many` return value
180
+ piles up zombie endpoints and wastes dispatch. Delete them as soon as
181
+ the push service answers 404/410.
182
+
183
+ ## Recap
184
+
185
+ - Install `[webpush]` and configure `WebPushSettings` (VAPID keys).
186
+ - Public key → frontend; private key → signs the pushes on the backend.
187
+ - `BaseWebPushSubscriptionModel` table (one row per device, unique `endpoint`) + `WebPushSubscriptionService` (`subscribe`/`unsubscribe`/`notify_user`) — the recommended path, with automatic pruning.
188
+ - The `WebPushClient` JSON (tempest-react-sdk) *is* the `WebPushSubscriptionSchema` — `subscribe`/`unsubscribe` map directly.
189
+ - Low-level path: `send()` for one target, `send_many()` for broadcast (returns the dead ones); handle `WebPushGoneError` (404/410) by pruning the store.
@@ -0,0 +1,188 @@
1
+ # Web Push
2
+
3
+ Notificações Web Push (assinadas com VAPID) para navegadores via
4
+ `WebPushDispatcher`. Embrulha o `pywebpush` síncrono em
5
+ `asyncio.to_thread` e expõe os dois erros que a aplicação realmente
6
+ trata: `WebPushGoneError` (HTTP 404/410 — apague a inscrição) e
7
+ `WebPushError` (qualquer outra falha). Requer o extra `[webpush]`
8
+ (`pywebpush` + `cryptography`).
9
+
10
+ ## Configuração VAPID
11
+
12
+ `WebPushSettings` traz `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY` e
13
+ `VAPID_SUBJECT`. A chave **pública** vai para o frontend (no
14
+ `pushManager.subscribe`); a **privada** assina cada push no backend. O
15
+ `sub` deve ser um URI `mailto:` ou `https:`.
16
+
17
+ ```python
18
+ # src/services/notifications.py
19
+ from tempest_fastapi_sdk import WebPushDispatcher
20
+
21
+ from src.core.settings import settings
22
+
23
+
24
+ # settings.webpush_kwargs() -> vapid_private_key + vapid_subject + ttl_seconds
25
+ dispatcher = WebPushDispatcher(**settings.webpush_kwargs())
26
+ ```
27
+
28
+ ## Tabela + serviço (recomendado)
29
+
30
+ Para guardar os aparelhos do usuário e entregar com poda automática, o
31
+ SDK traz a **tabela base** `BaseWebPushSubscriptionModel` (uma linha por
32
+ device, `endpoint` único) e o **serviço base** `WebPushSubscriptionService`
33
+ (salva, remove e envia, podando as mortas sozinho). Igual ao padrão de
34
+ auth, o SDK fornece a linha abstrata e o projeto cria a tabela concreta
35
+ com a FK pro seu `UserModel`:
36
+
37
+ ```python
38
+ # src/db/models/web_push_subscription.py
39
+ from sqlalchemy import ForeignKey
40
+ from sqlalchemy.orm import Mapped, mapped_column
41
+ from uuid import UUID
42
+
43
+ from tempest_fastapi_sdk import BaseWebPushSubscriptionModel
44
+
45
+
46
+ class WebPushSubscriptionModel(BaseWebPushSubscriptionModel):
47
+ """Inscrição Web Push de um device do usuário."""
48
+
49
+ __tablename__ = "web_push_subscriptions"
50
+
51
+ user_id: Mapped[UUID] = mapped_column(
52
+ ForeignKey("users.id", ondelete="CASCADE"),
53
+ nullable=False,
54
+ index=True,
55
+ )
56
+ ```
57
+
58
+ Monte o serviço com um `BaseRepository` da tabela + o dispatcher VAPID:
59
+
60
+ ```python
61
+ # src/api/dependencies/resources.py
62
+ from tempest_fastapi_sdk import BaseRepository, WebPushSubscriptionService
63
+
64
+ from src.core.settings import settings
65
+ from src.db.models import WebPushSubscriptionModel
66
+
67
+
68
+ def get_push_service(session: AsyncSession) -> WebPushSubscriptionService:
69
+ repo = BaseRepository(session, model=WebPushSubscriptionModel)
70
+ dispatcher = WebPushDispatcher(**settings.webpush_kwargs())
71
+ return WebPushSubscriptionService(repo, dispatcher)
72
+ ```
73
+
74
+ O serviço expõe:
75
+
76
+ | Método | O que faz |
77
+ | --- | --- |
78
+ | `subscribe(user_id, subscription, *, user_agent=None)` | Salva a inscrição, **idempotente por `endpoint`** — re-subscribe atualiza, não duplica. |
79
+ | `unsubscribe(endpoint)` | Remove a inscrição (no-op se não existe). |
80
+ | `list_for_user(user_id)` | Lista os devices do usuário. |
81
+ | `notify_user(user_id, payload)` | Envia pra todos os devices e **poda os mortos** (404/410) antes de retornar. Devolve quantos receberam. |
82
+
83
+ ## Alinhado com o tempest-react-sdk
84
+
85
+ O `WebPushClient` do [`tempest-react-sdk`](https://github.com/mauriciobenjamin700/tempest-react-sdk)
86
+ chama `onSubscribe(subscription)` e `onUnsubscribe(subscription)` com o
87
+ `PushSubscription.toJSON()` cru. Esse JSON é exatamente o
88
+ `WebPushSubscriptionSchema` (aliasa `expiration_time` ↔ `expirationTime`),
89
+ então o front bate direto nos endpoints abaixo:
90
+
91
+ ```python
92
+ # src/api/routers/push.py
93
+ from fastapi import APIRouter, Depends, status
94
+
95
+ from tempest_fastapi_sdk import WebPushSubscriptionSchema, WebPushSubscriptionService
96
+
97
+ router = APIRouter(prefix="/api/push", tags=["push"])
98
+
99
+
100
+ @router.post("/subscribe", status_code=status.HTTP_201_CREATED)
101
+ async def subscribe(
102
+ subscription: WebPushSubscriptionSchema,
103
+ user: CurrentUser, # sua dependency de auth
104
+ service: WebPushSubscriptionService = Depends(get_push_service),
105
+ ) -> dict[str, str]:
106
+ """Recebe o onSubscribe do WebPushClient e persiste o device."""
107
+ await service.subscribe(user.id, subscription)
108
+ return {"status": "subscribed"}
109
+
110
+
111
+ @router.post("/unsubscribe", status_code=status.HTTP_200_OK)
112
+ async def unsubscribe(
113
+ subscription: WebPushSubscriptionSchema,
114
+ service: WebPushSubscriptionService = Depends(get_push_service),
115
+ ) -> dict[str, str]:
116
+ """Recebe o onUnsubscribe e remove o device."""
117
+ await service.unsubscribe(subscription.endpoint)
118
+ return {"status": "unsubscribed"}
119
+ ```
120
+
121
+ Enviar pra um usuário (todos os devices, poda automática embutida):
122
+
123
+ ```python
124
+ delivered: int = await service.notify_user(
125
+ user.id,
126
+ {"title": "Pagamento confirmado", "body": "Pedido aprovado."},
127
+ )
128
+ ```
129
+
130
+ ## Enviar uma notificação (dispatcher direto)
131
+
132
+ O `payload` aceita `WebPushPayloadSchema`, `dict`, `str` ou `bytes`
133
+ (models e dicts viram JSON). Trate `WebPushGoneError` para podar a
134
+ inscrição morta do seu store.
135
+
136
+ ```python
137
+ from tempest_fastapi_sdk import (
138
+ WebPushGoneError,
139
+ WebPushPayloadSchema,
140
+ WebPushSubscriptionSchema,
141
+ )
142
+
143
+
144
+ async def notify_order_paid(
145
+ subscription: WebPushSubscriptionSchema,
146
+ order_id: str,
147
+ ) -> None:
148
+ payload = WebPushPayloadSchema(
149
+ title="Pagamento confirmado",
150
+ body=f"Pedido {order_id} aprovado.",
151
+ icon="/static/icons/order.png",
152
+ data={"orderId": order_id, "url": f"/orders/{order_id}"},
153
+ )
154
+ try:
155
+ await dispatcher.send(subscription, payload)
156
+ except WebPushGoneError:
157
+ await subscriptions_repo.delete_by_endpoint(subscription.endpoint)
158
+ ```
159
+
160
+ ## Broadcast com poda automática
161
+
162
+ `send_many()` dispara o mesmo payload concorrentemente
163
+ (`asyncio.gather`) e **retorna os endpoints mortos** (404/410) para você
164
+ remover — outras falhas são logadas, não levantadas.
165
+
166
+ ```python
167
+ async def broadcast(
168
+ subs: list[WebPushSubscriptionSchema],
169
+ payload: WebPushPayloadSchema,
170
+ ) -> None:
171
+ gone: list[str] = await dispatcher.send_many(subs, payload)
172
+ if gone:
173
+ await subscriptions_repo.delete_by_endpoints(gone)
174
+ ```
175
+
176
+ !!! warning "Sempre pode as inscrições mortas"
177
+ Inscrições expiram quando o usuário troca de device ou revoga a
178
+ permissão. Ignorar `WebPushGoneError` / o retorno do `send_many`
179
+ acumula endpoints zumbis e desperdiça dispatch. Apague-os assim que
180
+ o push service responder 404/410.
181
+
182
+ ## Recap
183
+
184
+ - Instale `[webpush]` e configure `WebPushSettings` (chaves VAPID).
185
+ - Chave pública → frontend; privada → assina os pushes no backend.
186
+ - Tabela `BaseWebPushSubscriptionModel` (1 linha por device, `endpoint` único) + `WebPushSubscriptionService` (`subscribe`/`unsubscribe`/`notify_user`) — o caminho recomendado, com poda automática.
187
+ - O JSON do `WebPushClient` (tempest-react-sdk) é o próprio `WebPushSubscriptionSchema` — `subscribe`/`unsubscribe` batem direto.
188
+ - Caminho baixo nível: `send()` para um destino, `send_many()` para broadcast (retorna mortos); trate `WebPushGoneError` (404/410) podando o store.
@@ -252,6 +252,8 @@ Gerada automaticamente a partir das docstrings do SDK via [`mkdocstrings`](https
252
252
  ### `tempest_fastapi_sdk.webpush`
253
253
 
254
254
  ::: tempest_fastapi_sdk.webpush.dispatcher.WebPushDispatcher
255
+ ::: tempest_fastapi_sdk.webpush.service.WebPushSubscriptionService
256
+ ::: tempest_fastapi_sdk.db.webpush_subscription_model.BaseWebPushSubscriptionModel
255
257
  ::: tempest_fastapi_sdk.webpush.schemas.WebPushSubscriptionSchema
256
258
  ::: tempest_fastapi_sdk.webpush.schemas.WebPushPayloadSchema
257
259
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tempest-fastapi-sdk"
3
- version = "0.78.0"
3
+ version = "0.80.0"
4
4
  description = "Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -133,6 +133,7 @@ from tempest_fastapi_sdk.db import (
133
133
  BaseUserRecoveryCodeModel,
134
134
  BaseUserRefreshTokenModel,
135
135
  BaseUserTokenModel,
136
+ BaseWebPushSubscriptionModel,
136
137
  DatabaseBackup,
137
138
  DestructiveMigrationError,
138
139
  MFAMixin,
@@ -149,6 +150,7 @@ from tempest_fastapi_sdk.db import (
149
150
  make_user_recovery_code_model,
150
151
  make_user_refresh_token_model,
151
152
  make_user_token_model,
153
+ make_web_push_subscription_model,
152
154
  reorder_base_columns_first,
153
155
  snapshot_model,
154
156
  )
@@ -334,6 +336,7 @@ from tempest_fastapi_sdk.webpush import (
334
336
  WebPushKeysSchema,
335
337
  WebPushPayloadSchema,
336
338
  WebPushSubscriptionSchema,
339
+ WebPushSubscriptionService,
337
340
  )
338
341
  from tempest_fastapi_sdk.websockets import (
339
342
  WebSocketConnection,
@@ -342,7 +345,7 @@ from tempest_fastapi_sdk.websockets import (
342
345
  make_websocket_router,
343
346
  )
344
347
 
345
- __version__: str = "0.78.0"
348
+ __version__: str = "0.80.0"
346
349
 
347
350
  __all__: list[str] = [
348
351
  "BASE_COLUMN_ORDER",
@@ -398,6 +401,7 @@ __all__: list[str] = [
398
401
  "BaseUserRecoveryCodeModel",
399
402
  "BaseUserRefreshTokenModel",
400
403
  "BaseUserTokenModel",
404
+ "BaseWebPushSubscriptionModel",
401
405
  "BodySizeLimitMiddleware",
402
406
  "CEPField",
403
407
  "CNPJField",
@@ -561,6 +565,7 @@ __all__: list[str] = [
561
565
  "WebPushPayloadSchema",
562
566
  "WebPushSettings",
563
567
  "WebPushSubscriptionSchema",
568
+ "WebPushSubscriptionService",
564
569
  "WebSocketConnection",
565
570
  "WebSocketHub",
566
571
  "WebSocketSettings",
@@ -626,6 +631,7 @@ __all__: list[str] = [
626
631
  "make_user_recovery_code_model",
627
632
  "make_user_refresh_token_model",
628
633
  "make_user_token_model",
634
+ "make_web_push_subscription_model",
629
635
  "make_websocket_router",
630
636
  "modify_dict",
631
637
  "negotiate_locale",