tempest-fastapi-sdk 0.82.0__tar.gz → 0.87.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 (475) hide show
  1. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/CHANGELOG.md +118 -0
  2. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/CLAUDE.md +66 -24
  3. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/PKG-INFO +38 -31
  4. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/README.md +34 -30
  5. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/admin.en.md +110 -3
  6. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/admin.md +108 -3
  7. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/auth-flow.en.md +117 -0
  8. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/auth-flow.md +116 -0
  9. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/cache.en.md +2 -1
  10. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/cache.md +2 -1
  11. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/index.en.md +1 -0
  12. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/index.md +1 -0
  13. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/security.en.md +2 -1
  14. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/security.md +2 -1
  15. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/sessions.en.md +4 -2
  16. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/sessions.md +4 -2
  17. tempest_fastapi_sdk-0.87.0/docs/recipes/vision.en.md +128 -0
  18. tempest_fastapi_sdk-0.87.0/docs/recipes/vision.md +127 -0
  19. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/reference.md +18 -0
  20. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/mkdocs.yml +1 -0
  21. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/pyproject.toml +18 -1
  22. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/__init__.py +17 -1
  23. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/__init__.py +8 -0
  24. tempest_fastapi_sdk-0.87.0/tempest_fastapi_sdk/admin/actions.py +160 -0
  25. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/config.py +58 -0
  26. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/forms.py +16 -2
  27. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/router.py +287 -41
  28. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/static/admin.css +18 -0
  29. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/form.html +4 -1
  30. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/list.html +16 -4
  31. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/dependencies/auth.py +28 -7
  32. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/__init__.py +14 -0
  33. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/router.py +234 -50
  34. tempest_fastapi_sdk-0.87.0/tempest_fastapi_sdk/auth/token_delivery.py +158 -0
  35. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/settings/mixins.py +76 -1
  36. tempest_fastapi_sdk-0.87.0/tempest_fastapi_sdk/vision/__init__.py +85 -0
  37. tempest_fastapi_sdk-0.87.0/tempest_fastapi_sdk/vision/mapping.py +123 -0
  38. tempest_fastapi_sdk-0.87.0/tempest_fastapi_sdk/vision/schemas.py +111 -0
  39. tempest_fastapi_sdk-0.87.0/tests/admin/test_actions.py +183 -0
  40. tempest_fastapi_sdk-0.87.0/tests/admin/test_rich_filters.py +176 -0
  41. tempest_fastapi_sdk-0.87.0/tests/admin/test_upload_field.py +161 -0
  42. tempest_fastapi_sdk-0.87.0/tests/auth/test_cookie_delivery.py +303 -0
  43. tempest_fastapi_sdk-0.87.0/tests/vision/test_vision.py +95 -0
  44. tempest_fastapi_sdk-0.87.0/tests/websockets/__init__.py +0 -0
  45. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/uv.lock +297 -3
  46. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/.github/workflows/ci.yml +0 -0
  47. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/.github/workflows/docs.yml +0 -0
  48. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/.github/workflows/release-pypi.yml +0 -0
  49. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/.gitignore +0 -0
  50. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/.python-version +0 -0
  51. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/Makefile +0 -0
  52. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/architecture.en.md +0 -0
  53. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/architecture.md +0 -0
  54. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/changelog.en.md +0 -0
  55. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/changelog.md +0 -0
  56. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/contributing.en.md +0 -0
  57. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/contributing.md +0 -0
  58. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/index.en.md +0 -0
  59. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/index.md +0 -0
  60. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/installation.en.md +0 -0
  61. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/installation.md +0 -0
  62. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/index.en.md +0 -0
  63. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/index.md +0 -0
  64. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/api.en.md +0 -0
  65. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/api.md +0 -0
  66. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/business-rules.en.md +0 -0
  67. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/business-rules.md +0 -0
  68. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/domain.en.md +0 -0
  69. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/domain.md +0 -0
  70. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/flows.en.md +0 -0
  71. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/flows.md +0 -0
  72. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/index.en.md +0 -0
  73. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/learning/marketplace/index.md +0 -0
  74. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/migration.en.md +0 -0
  75. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/migration.md +0 -0
  76. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/audit-trail.en.md +0 -0
  77. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/audit-trail.md +0 -0
  78. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/br-helpers.en.md +0 -0
  79. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/br-helpers.md +0 -0
  80. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/cli.en.md +0 -0
  81. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/cli.md +0 -0
  82. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/database.en.md +0 -0
  83. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/database.md +0 -0
  84. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/deploy-safety.en.md +0 -0
  85. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/deploy-safety.md +0 -0
  86. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/downloads.en.md +0 -0
  87. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/downloads.md +0 -0
  88. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/email.en.md +0 -0
  89. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/email.md +0 -0
  90. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/feature-flags.en.md +0 -0
  91. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/feature-flags.md +0 -0
  92. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/fields.en.md +0 -0
  93. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/fields.md +0 -0
  94. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/http-client.en.md +0 -0
  95. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/http-client.md +0 -0
  96. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/http.en.md +0 -0
  97. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/http.md +0 -0
  98. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/idempotency.en.md +0 -0
  99. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/idempotency.md +0 -0
  100. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/logging.en.md +0 -0
  101. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/logging.md +0 -0
  102. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/metrics.en.md +0 -0
  103. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/metrics.md +0 -0
  104. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/mfa.en.md +0 -0
  105. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/mfa.md +0 -0
  106. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/multi-tenant.en.md +0 -0
  107. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/multi-tenant.md +0 -0
  108. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/observability.en.md +0 -0
  109. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/observability.md +0 -0
  110. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/offline-sync.en.md +0 -0
  111. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/offline-sync.md +0 -0
  112. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/outbox.en.md +0 -0
  113. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/outbox.md +0 -0
  114. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/queue-tasks.en.md +0 -0
  115. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/queue-tasks.md +0 -0
  116. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/realtime.en.md +0 -0
  117. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/realtime.md +0 -0
  118. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/refresh-tokens.en.md +0 -0
  119. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/refresh-tokens.md +0 -0
  120. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/sse.en.md +0 -0
  121. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/sse.md +0 -0
  122. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/storage.en.md +0 -0
  123. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/storage.md +0 -0
  124. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/stored-files.en.md +0 -0
  125. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/stored-files.md +0 -0
  126. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/testing.en.md +0 -0
  127. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/testing.md +0 -0
  128. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/typing.en.md +0 -0
  129. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/typing.md +0 -0
  130. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/uploads.en.md +0 -0
  131. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/uploads.md +0 -0
  132. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/utilities.en.md +0 -0
  133. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/utilities.md +0 -0
  134. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/webpush.en.md +0 -0
  135. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/webpush.md +0 -0
  136. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/websocket.en.md +0 -0
  137. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/recipes/websocket.md +0 -0
  138. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/reference.en.md +0 -0
  139. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/roadmap.en.md +0 -0
  140. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/roadmap.md +0 -0
  141. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/tutorial.en.md +0 -0
  142. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/docs/tutorial.md +0 -0
  143. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/mkdocs_hooks/llmstxt.py +0 -0
  144. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/scripts/extract_recipe.py +0 -0
  145. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
  146. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/discovery.py +0 -0
  147. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/session.py +0 -0
  148. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/site.py +0 -0
  149. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
  150. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
  151. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
  152. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
  153. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
  154. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
  155. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/admin/theme.py +0 -0
  156. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
  157. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
  158. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
  159. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
  160. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
  161. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
  162. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
  163. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
  164. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
  165. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
  166. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
  167. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
  168. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
  169. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
  170. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
  171. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
  172. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
  173. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
  174. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/server.py +0 -0
  175. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/static.py +0 -0
  176. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
  177. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
  178. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
  179. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/locale.py +0 -0
  180. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
  181. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
  182. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/service.py +0 -0
  183. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
  184. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
  185. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
  186. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
  187. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
  188. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
  189. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
  190. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
  191. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
  192. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
  193. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
  194. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
  195. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
  196. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
  197. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
  198. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
  199. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
  200. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
  201. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
  202. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/Dockerfile.tmpl +0 -0
  203. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
  204. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/dockerignore.tmpl +0 -0
  205. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
  206. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
  207. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
  208. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
  209. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
  210. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
  211. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
  212. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
  213. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
  214. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
  215. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
  216. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
  217. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
  218. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
  219. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
  220. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
  221. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
  222. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
  223. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
  224. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
  225. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
  226. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
  227. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
  228. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
  229. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
  230. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/config.py +0 -0
  231. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/db.py +0 -0
  232. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
  233. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
  234. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
  235. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/main.py +0 -0
  236. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/new.py +0 -0
  237. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
  238. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
  239. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/cli/user.py +0 -0
  240. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
  241. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
  242. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
  243. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/core/context.py +0 -0
  244. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/core/enums.py +0 -0
  245. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/core/logging.py +0 -0
  246. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/core/typed.py +0 -0
  247. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
  248. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
  249. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
  250. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
  251. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/audit.py +0 -0
  252. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/backup.py +0 -0
  253. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/connection.py +0 -0
  254. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
  255. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
  256. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/model.py +0 -0
  257. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
  258. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/repository.py +0 -0
  259. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
  260. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
  261. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
  262. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
  263. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/user_refresh_token_model.py +0 -0
  264. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
  265. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/db/webpush_subscription_model.py +0 -0
  266. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
  267. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
  268. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
  269. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
  270. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
  271. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
  272. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
  273. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
  274. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
  275. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
  276. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
  277. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
  278. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
  279. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
  280. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/flags/service.py +0 -0
  281. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/py.typed +0 -0
  282. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
  283. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
  284. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
  285. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
  286. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
  287. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
  288. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
  289. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
  290. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
  291. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/services/base.py +0 -0
  292. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/services/file_mixin.py +0 -0
  293. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
  294. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
  295. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
  296. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
  297. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
  298. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
  299. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
  300. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
  301. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/settings/base.py +0 -0
  302. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sse/__init__.py +0 -0
  303. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sse/broker.py +0 -0
  304. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/sse/event_stream.py +0 -0
  305. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
  306. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
  307. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
  308. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
  309. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
  310. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
  311. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/testing/database.py +0 -0
  312. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
  313. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
  314. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
  315. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
  316. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
  317. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/download.py +0 -0
  318. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/email.py +0 -0
  319. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/fields.py +0 -0
  320. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
  321. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
  322. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
  323. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/log.py +0 -0
  324. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
  325. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
  326. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/password.py +0 -0
  327. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
  328. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
  329. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
  330. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
  331. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
  332. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
  333. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
  334. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/webpush/router.py +0 -0
  335. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
  336. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/webpush/service.py +0 -0
  337. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
  338. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
  339. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
  340. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
  341. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/__init__.py +0 -0
  342. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/__init__.py +0 -0
  343. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_auth.py +0 -0
  344. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_discovery.py +0 -0
  345. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_forms.py +0 -0
  346. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_logs_nav.py +0 -0
  347. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_mfa.py +0 -0
  348. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_router.py +0 -0
  349. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_site.py +0 -0
  350. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_theme.py +0 -0
  351. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/admin/test_user_model.py +0 -0
  352. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/__init__.py +0 -0
  353. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_body_size.py +0 -0
  354. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_cookies.py +0 -0
  355. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_cors.py +0 -0
  356. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_csrf.py +0 -0
  357. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_dependencies_auth.py +0 -0
  358. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_graceful.py +0 -0
  359. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_handlers.py +0 -0
  360. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_health_router.py +0 -0
  361. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_idempotency.py +0 -0
  362. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_jwt_dependency.py +0 -0
  363. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_logs_router.py +0 -0
  364. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_oauth.py +0 -0
  365. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_prometheus.py +0 -0
  366. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_rate_limit.py +0 -0
  367. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_rate_limit_extras.py +0 -0
  368. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_request_id_middleware.py +0 -0
  369. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_role_dependency.py +0 -0
  370. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_server.py +0 -0
  371. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_static.py +0 -0
  372. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_tool_spec.py +0 -0
  373. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_tracing.py +0 -0
  374. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_webhooks.py +0 -0
  375. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/api/test_webhooks_rsa.py +0 -0
  376. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/auth/__init__.py +0 -0
  377. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/auth/test_guards.py +0 -0
  378. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/auth/test_locale.py +0 -0
  379. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/auth/test_mfa.py +0 -0
  380. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/auth/test_refresh.py +0 -0
  381. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/auth/test_refresh_db.py +0 -0
  382. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/auth/test_service.py +0 -0
  383. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cache/__init__.py +0 -0
  384. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cache/test_decorator.py +0 -0
  385. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cache/test_invalidation.py +0 -0
  386. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cache/test_redis_manager.py +0 -0
  387. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/__init__.py +0 -0
  388. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_config.py +0 -0
  389. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_db.py +0 -0
  390. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_db_seed.py +0 -0
  391. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_docker_compose.py +0 -0
  392. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_generate.py +0 -0
  393. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_lint_strictness.py +0 -0
  394. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_main.py +0 -0
  395. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_secrets.py +0 -0
  396. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/cli/test_user.py +0 -0
  397. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/conftest.py +0 -0
  398. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/controllers/__init__.py +0 -0
  399. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/controllers/test_base.py +0 -0
  400. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/core/__init__.py +0 -0
  401. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/core/test_context.py +0 -0
  402. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/core/test_enums.py +0 -0
  403. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/core/test_logging.py +0 -0
  404. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/core/test_typed.py +0 -0
  405. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/__init__.py +0 -0
  406. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_alembic_hooks.py +0 -0
  407. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_audit.py +0 -0
  408. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_backup.py +0 -0
  409. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_bulk_ops.py +0 -0
  410. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_connection.py +0 -0
  411. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_migrations.py +0 -0
  412. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_mixins.py +0 -0
  413. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_model.py +0 -0
  414. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_outbox.py +0 -0
  415. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_repository.py +0 -0
  416. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_safe_upgrade.py +0 -0
  417. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_slow_query.py +0 -0
  418. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/db/test_tenant.py +0 -0
  419. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/exceptions/__init__.py +0 -0
  420. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/exceptions/test_exceptions.py +0 -0
  421. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/exceptions/test_i18n.py +0 -0
  422. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/flags/__init__.py +0 -0
  423. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/flags/test_flags.py +0 -0
  424. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/queue/__init__.py +0 -0
  425. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/queue/test_manager.py +0 -0
  426. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/schemas/__init__.py +0 -0
  427. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/schemas/test_base.py +0 -0
  428. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/schemas/test_cursor_pagination.py +0 -0
  429. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/schemas/test_link_headers.py +0 -0
  430. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/schemas/test_pagination.py +0 -0
  431. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/schemas/test_response.py +0 -0
  432. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/services/__init__.py +0 -0
  433. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/services/test_base.py +0 -0
  434. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/services/test_file_mixin.py +0 -0
  435. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/sessions/__init__.py +0 -0
  436. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/sessions/test_sessions.py +0 -0
  437. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/settings/__init__.py +0 -0
  438. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/settings/test_base.py +0 -0
  439. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/settings/test_mixins.py +0 -0
  440. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/sse/__init__.py +0 -0
  441. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/sse/test_broker.py +0 -0
  442. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/sse/test_event_stream.py +0 -0
  443. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/storage/__init__.py +0 -0
  444. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/storage/test_minio_client.py +0 -0
  445. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/tasks/__init__.py +0 -0
  446. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/tasks/test_manager.py +0 -0
  447. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/tasks/test_scheduler.py +0 -0
  448. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/testing/__init__.py +0 -0
  449. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/testing/test_database.py +0 -0
  450. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/__init__.py +0 -0
  451. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_client_ip.py +0 -0
  452. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_datetime.py +0 -0
  453. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_dict.py +0 -0
  454. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_download.py +0 -0
  455. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_email.py +0 -0
  456. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_fields.py +0 -0
  457. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_http_client.py +0 -0
  458. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_jwt.py +0 -0
  459. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_lazy_extras.py +0 -0
  460. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_locations.py +0 -0
  461. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_log.py +0 -0
  462. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_metrics.py +0 -0
  463. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_opaque_token.py +0 -0
  464. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_password.py +0 -0
  465. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_regex.py +0 -0
  466. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_storage_backends.py +0 -0
  467. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_throttle.py +0 -0
  468. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/utils/test_upload.py +0 -0
  469. {tempest_fastapi_sdk-0.82.0/tests/webpush → tempest_fastapi_sdk-0.87.0/tests/vision}/__init__.py +0 -0
  470. {tempest_fastapi_sdk-0.82.0/tests/websockets → tempest_fastapi_sdk-0.87.0/tests/webpush}/__init__.py +0 -0
  471. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/webpush/test_dispatcher.py +0 -0
  472. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/webpush/test_router.py +0 -0
  473. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/webpush/test_schemas.py +0 -0
  474. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/webpush/test_service.py +0 -0
  475. {tempest_fastapi_sdk-0.82.0 → tempest_fastapi_sdk-0.87.0}/tests/websockets/test_hub_and_router.py +0 -0
@@ -5,6 +5,124 @@ 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.87.0] — 2026-07-02
9
+
10
+ ### Added
11
+
12
+ - **Configurable token delivery for the auth router.** `make_auth_router`
13
+ now supports three ways of handing back the JWT pair, selected by
14
+ `AUTH_TOKEN_DELIVERY` (or the `token_delivery=` argument):
15
+ - `"bearer"` (default) — tokens in the JSON body only. Unchanged,
16
+ fully backward-compatible behaviour.
17
+ - `"cookie"` — `access_token` / `refresh_token` set as `HttpOnly`
18
+ cookies on `/auth/login`, `/auth/refresh`, `/auth/logout`; the body
19
+ omits the token values (safer against XSS). `POST /auth/refresh`
20
+ reads the refresh token from the cookie and rotates the pair;
21
+ `POST /auth/logout` clears the cookies (and revokes the refresh
22
+ family when a `refresh_token_model` is wired).
23
+ - `"both"` — the bearer endpoints stay at `/auth/*` and a parallel
24
+ cookie set is mounted at `/auth/cookie/*`, so one backend can serve
25
+ web (cookie) and mobile/API (bearer) clients.
26
+ - New `AUTH_COOKIE_SECURE`, `AUTH_COOKIE_SAMESITE`, `AUTH_COOKIE_DOMAIN`,
27
+ `AUTH_ACCESS_COOKIE_NAME` and `AUTH_REFRESH_COOKIE_NAME` settings tune
28
+ the cookie security attributes.
29
+ - New public exports: `TokenDelivery`, `AuthCookieConfig`,
30
+ `apply_auth_cookies`, `clear_auth_cookies`.
31
+ - `make_bearer_token_dependency` / `make_jwt_user_dependency` gained a
32
+ `cookie_name=` argument: when set, the access token is read from that
33
+ cookie if the `Authorization` header is absent (header still wins), so
34
+ the same guarded routes work in cookie mode.
35
+
36
+ ### Notes
37
+
38
+ - Activation, signup auto-login and the MFA-verify step still return the
39
+ JWT pair in the body regardless of `AUTH_TOKEN_DELIVERY` — cookie
40
+ delivery covers the login / refresh / logout session lifecycle.
41
+
42
+ ## [0.86.0] — 2026-06-28
43
+
44
+ ### Added
45
+
46
+ - **Admin rich list filters.** `list_filter` fields now auto-pick a
47
+ widget by column type instead of rendering a useful dropdown only for
48
+ booleans: **enum** columns become a member dropdown, **foreign keys**
49
+ (whose target has a registered `AdminModel`) become a related-row
50
+ dropdown, **date/datetime** columns become an inclusive date-range
51
+ (two date inputs → `<field>__gte` / `<field>__lte`), and any other
52
+ column becomes a text input (equality). Booleans keep the Yes/No
53
+ dropdown. All filters preserve search / sort / pagination in the URL.
54
+
55
+ ## [0.85.0] — 2026-06-28
56
+
57
+ ### Added
58
+
59
+ - **Admin file / image upload fields.** `AdminModel` gained
60
+ `upload_fields=[...]` + `upload_storage=...`: listed String columns
61
+ render as file inputs in the create/edit form (which auto-switches to
62
+ `multipart/form-data`), the posted file is streamed to the storage
63
+ backend (`LocalUploadStorage` / `MinIOUploadStorage`), and the returned
64
+ storage key is written to the column. On edit, omitting the file keeps
65
+ the current value; on create, a missing file for a non-nullable column
66
+ is a required-field error. Registering `upload_fields` without
67
+ `upload_storage` raises `ValueError`.
68
+
69
+ ## [0.84.0] — 2026-06-28
70
+
71
+ ### Added
72
+
73
+ - **Admin custom actions (`@admin_action`).** Beyond the three hardcoded
74
+ bulk operations (activate / deactivate / delete), the admin now takes
75
+ user-defined actions: decorate an async function with `@admin_action`
76
+ and register it via `AdminModel(actions=[...])`. Each renders in the
77
+ list view's bulk dropdown (namespaced `custom:<name>` so it can't
78
+ collide with the built-ins), runs on the checked rows, and flashes a
79
+ banner from its `AdminActionResult`. The handler receives an
80
+ `AdminActionContext` (selected ids, a request-scoped repository, the DB
81
+ session, the request, the admin session, and the acting principal) and
82
+ stays directly callable/testable — the decorator only attaches
83
+ metadata. Exported from `tempest_fastapi_sdk` and
84
+ `tempest_fastapi_sdk.admin` (`admin_action`, `AdminAction`,
85
+ `AdminActionContext`, `AdminActionResult`).
86
+
87
+ ## [0.83.0] — 2026-06-28
88
+
89
+ ### Added
90
+
91
+ - **Computer-vision integration via the `[vision]` extra
92
+ (`ort-vision-sdk`).** New `tempest_fastapi_sdk.vision` submodule wraps
93
+ the ONNX Runtime inference library with the FastAPI layer it lacks:
94
+ Pydantic response schemas (`DetectionSchema`, `ClassificationSchema`,
95
+ `SegmentationSchema`, `BoundingBoxSchema`, `ClassProbabilitySchema`)
96
+ and mappers (`to_detection_schemas`, `to_classification_schema`,
97
+ `to_segmentation_schemas`) that convert a model result into them. The
98
+ `Detector` / `Classifier` / `Segmenter` task classes are re-exported
99
+ **lazily** — accessing one without the extra raises a clear
100
+ `ImportError` pointing at `[vision]`; the schemas and mappers carry no
101
+ such dependency. Like `cache` / `queue` / `tasks`, vision is
102
+ submodule-only (`from tempest_fastapi_sdk.vision import Detector`).
103
+
104
+ ## [0.82.1] — 2026-06-28
105
+
106
+ ### Fixed
107
+
108
+ - **Docs: removed code that the API never offered.** A doc audit
109
+ (cross-checking every `tempest_fastapi_sdk` import and example against
110
+ the package) found and fixed drift in the README:
111
+ - The brute-force throttling recipe invented `MemoryThrottleBackend` /
112
+ `RedisThrottleBackend`, `throttle.check()` returning a `ThrottleStatus`
113
+ enum, `record_failure()`, and `lock_seconds=` — none exist. Rewritten
114
+ to the real API (`AttemptThrottle(backend, max_attempts=, window_seconds=)`
115
+ with `raise_if_blocked` / `hit` / `reset` / `status`).
116
+ - The client-IP recipe used `trusted_proxies=` / `accept_private=` — the
117
+ real parameter is `trusted_header=`.
118
+ - The cookie recipe treated `SameSite` as a `BaseStrEnum` (`SameSite.LAX`)
119
+ with `same_site=` / `key=` kwargs and an auto-`Secure` claim; `SameSite`
120
+ is a `Literal` alias and `set_cookie` takes positional `name`/`value`
121
+ + `samesite=`.
122
+ - `AsyncRedisManager` was imported from the top level in several recipes
123
+ (cache / sessions / security) — it lives in `tempest_fastapi_sdk.cache`
124
+ (submodule-only, like `queue` / `tasks`). No code changes.
125
+
8
126
  ## [0.82.0] — 2026-06-28
9
127
 
10
128
  ### Added
@@ -88,8 +88,32 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
88
88
  - **Pagination** — offset + cursor.
89
89
  - **Settings mixins** — every `*Settings` carries
90
90
  `title`/`description`/`examples` on every field.
91
- - **SSE** — `EventStream`, `sse_response`.
92
- - **Throttle** — `AttemptThrottle` (memory + Redis).
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).
94
+ - **Throttle** — `AttemptThrottle` (any `ThrottleBackend`, e.g.
95
+ `redis.asyncio.Redis`; no in-memory backend bundled).
96
+ - **Base CRUD layers** — `BaseService[Repo, Resp, UpdateT]` and
97
+ `BaseController[Service, Resp, UpdateT]` with
98
+ `get_by_id`/`get_or_none`/`list`/`paginate`/`count`/`exists`/`update`/
99
+ `delete`; `update` is partial-aware (PUT/PATCH) and `UpdateT` is an
100
+ optional 3rd generic (defaults to `BaseSchema`, PEP 696).
101
+ - **Base enums** — `BaseStrEnum` / `BaseIntEnum` with
102
+ `values`/`keys`/`choices`/`to_dict`/`from_value`/`has_value`/`has_key`.
103
+ - **Validated field types** — `tempest_fastapi_sdk.utils` Annotated
104
+ Pydantic types: `PositiveIntField`/`NonNegativeIntField`/`CentsField`/
105
+ `PortField`/`PositiveFloatField`/`NonNegativeFloatField`/`PercentField`/
106
+ `RatioField`/`LatitudeField`/`LongitudeField`/`PriceField`/
107
+ `NonEmptyStrField`/`SlugField`/`HexColorField`.
108
+ - **Runtime typing** — `strict_types` / `typed` / `require_annotations`
109
+ decorators (over `pydantic.validate_call`); ruff `ANN` enabled in the
110
+ SDK and `tempest new` templates (ANN401 off — `Any` is valid); a
111
+ `[tool.tempest] typing_strictness` knob (`lenient`/`standard`/`strict`,
112
+ `--strictness` override) layered onto `tempest lint`/`fix`/`type`/`check`.
113
+ - **Vision** (`[vision]` extra) — `tempest_fastapi_sdk.vision` wrapping
114
+ `ort-vision-sdk`: lazy `Detector`/`Classifier`/`Segmenter` + prediction
115
+ schemas + `to_detection_schemas`/`to_classification_schema`/
116
+ `to_segmentation_schemas` mappers.
93
117
  - **Upload** — `UploadUtils` with pluggable backends
94
118
  (`LocalUploadStorage`, `MinIOUploadStorage`), download helpers,
95
119
  presigned URLs.
@@ -99,17 +123,26 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
99
123
  - **Email** — SMTP via `EmailUtils` + Jinja2 template rendering
100
124
  with bundled defaults (`activation.html`, `password_reset.html`)
101
125
  shadowable by the project's `template_dir`.
102
- - **WebPush** + webhook signatures.
126
+ - **WebPush** `WebPushDispatcher` (`send`/`send_many`, 404/410
127
+ pruning), subscription storage (`BaseWebPushSubscriptionModel` +
128
+ `make_web_push_subscription_model`) + `WebPushSubscriptionService`
129
+ (`subscribe`/`unsubscribe`/`list_for_user`/`notify_user` with
130
+ auto-prune of gone endpoints) + `make_web_push_router` (opt-in
131
+ `/subscribe` + `/unsubscribe`, aligned with `tempest-react-sdk`);
132
+ webhook signatures.
103
133
  - **Cache** — Redis manager + `@cached`.
104
134
  - **Queue / tasks** — FastStream + TaskIQ wrappers.
105
- - **BR validators** — CPF/CNPJ/CEP/phone.
135
+ - **BR validators** — CPF/CNPJ/CEP/phone, with `*Field` Pydantic types
136
+ (`CPFField`/`CNPJField`/`CPFOrCNPJField`/`PhoneBRField`/`CEPField`;
137
+ pre-0.76 unsuffixed names kept as deprecated aliases).
106
138
  - **BR localities** — `UF` (StrEnum, 27 siglas) + `Region`
107
139
  (5 macro-regiões IBGE), `StateBR`/`CityBR` schemas, offline
108
140
  dataset of 27 states + 5606 municipalities (IBGE-derived,
109
141
  DF as 36 administrative regions), `list_states`/`get_state`/
110
142
  `cities_by_uf`/`states_by_region`, `is_valid_uf`/`normalize_uf`,
111
143
  `is_valid_city`/`normalize_city` (accent/case-insensitive),
112
- `UFField`/`CityNameField`.
144
+ `UFField`/`CityNameField`, plus `ChoiceBR` + `uf_choices`/
145
+ `region_choices`/`city_choices` (frontend `<select>` choices).
113
146
  - **Rate limit** — `RateLimitMiddleware` (sliding window) with
114
147
  pluggable store (`MemoryRateLimitStore` / `RedisRateLimitStore`,
115
148
  atomic Lua) and per-principal key extractors (`key_by_ip`,
@@ -131,7 +164,11 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
131
164
  - **Admin panel** — Jinja + HTMX (`AdminSite`, `AdminModel`,
132
165
  `make_admin_router`), typed theming via `AdminTheme` (colors /
133
166
  logo / favicon / font / radius / footer / dark mode /
134
- `custom_css_url`, injected as `:root` overrides).
167
+ `custom_css_url`, injected as `:root` overrides), custom bulk actions
168
+ (`@admin_action` + `AdminModel(actions=[...])`, `AdminActionContext` /
169
+ `AdminActionResult`), file/image upload fields (`AdminModel(
170
+ upload_fields=[...], upload_storage=...)`), rich list filters
171
+ (bool/enum/FK select, date-range, text — auto by column type).
135
172
  - **CLI** — `tempest new` (scaffolds layered service +
136
173
  docker-compose + multi-stage uv `Dockerfile`/`.dockerignore`),
137
174
  `tempest generate --docker` (regen compose) / `--dockerfile`
@@ -169,41 +206,46 @@ then move it up to the covers list.
169
206
  foundation the user asked for first; the functional Tier 1 items below
170
207
  inherit the look for free. Now in the covers list.
171
208
 
209
+ **Shipped — custom actions (v0.84.0).** `@admin_action` decorator +
210
+ `AdminModel(actions=[...])` + `AdminActionContext`/`AdminActionResult`;
211
+ custom entries render in the bulk dropdown (namespaced `custom:<name>`),
212
+ run on the checked rows, and flash a banner on the list view. Now in the
213
+ covers list.
214
+
215
+ **Shipped — file / image upload field (v0.85.0).** `AdminModel(
216
+ upload_fields=[...], upload_storage=...)` renders String columns as file
217
+ inputs, streams the upload to `LocalUploadStorage` / `MinIOUploadStorage`,
218
+ and stores the returned key. Now in the covers list.
219
+
220
+ **Shipped — rich filters (v0.86.0).** `list_filter` fields auto-pick a
221
+ widget by column type: bool / enum / FK → select, date/datetime →
222
+ inclusive date-range (two inputs → `__gte`/`__lte`), other → text.
223
+ Now in the covers list.
224
+
172
225
  **Tier 1 — high value, reuses an existing engine (low effort):**
173
226
 
174
- 1. **Custom actions (NEXT)** — `@admin_action` decorator on `AdminModel`
175
- for user-defined row / bulk operations (Django `actions`, Nova
176
- actions). Today only 3 are hardcoded (activate / deactivate /
177
- delete). This is the foundation the rest build on.
178
- 2. **File / image upload field** — a new form widget wired to the
179
- existing `UploadUtils` (`LocalUploadStorage` / `MinIOUploadStorage`).
180
- Engine is already shipped; admin just needs the widget + storage
181
- binding.
182
- 3. **Rich filters** — enum / choice / FK / date-range filters in the
183
- list view (today only boolean fields auto-render a filter dropdown).
184
- Quick UX win.
185
- 4. **Audit history viewer** — a per-row change timeline wired to the
227
+ 1. **Audit history viewer (NEXT)** — a per-row change timeline wired to the
186
228
  existing `BaseAuditLogModel` + `diff_snapshots`. Today the detail
187
229
  view only shows `created_by` / `updated_by` stamps, not full history.
188
230
  Engine is already shipped.
189
231
 
190
232
  **Tier 2 — high value, medium effort:**
191
233
 
192
- 5. **Autocomplete FK fields** — HTMX search endpoint backing FK inputs,
234
+ 2. **Autocomplete FK fields** — HTMX search endpoint backing FK inputs,
193
235
  removing the 1000-row `<select>` cap and the plain-UUID fallback
194
236
  (Django `autocomplete_fields`, Nova search).
195
- 6. **Inlines / nested relations** — edit child rows inside the parent's
237
+ 3. **Inlines / nested relations** — edit child rows inside the parent's
196
238
  detail / edit view (Django `StackedInline` / `TabularInline`).
197
- 7. **Dashboard business metrics / charts** — value / trend / partition
239
+ 4. **Dashboard business metrics / charts** — value / trend / partition
198
240
  cards (Nova metrics), wired to the existing metrics module. Distinct
199
241
  from today's system CPU/RAM/disk panel.
200
242
 
201
243
  **Tier 3 — nice-to-have:**
202
244
 
203
- 8. **RBAC granular** — per-model / per-action admin permissions beyond
245
+ 5. **RBAC granular** — per-model / per-action admin permissions beyond
204
246
  today's `is_admin` + `can_create` / `can_edit` / `can_delete`.
205
- 9. **CSV import** — bulk upload counterpart to the existing export.
206
- 10. **Lenses** — saved alternate views / queries per model (Nova).
247
+ 6. **CSV import** — bulk upload counterpart to the existing export.
248
+ 7. **Lenses** — saved alternate views / queries per model (Nova).
207
249
 
208
250
  Origin: competitor gap analysis (Django Admin, Laravel Nova, SQLAdmin,
209
251
  Starlette-Admin) run 2026-06-26. Do **not** treat the tiers as locked —
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tempest-fastapi-sdk
3
- Version: 0.82.0
3
+ Version: 0.87.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
@@ -49,6 +49,7 @@ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.48b0; extra == 'all'
49
49
  Requires-Dist: opentelemetry-instrumentation-httpx>=0.48b0; extra == 'all'
50
50
  Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.48b0; extra == 'all'
51
51
  Requires-Dist: opentelemetry-sdk>=1.27.0; extra == 'all'
52
+ Requires-Dist: ort-vision-sdk>=0.4.0; extra == 'all'
52
53
  Requires-Dist: prometheus-client>=0.20.0; extra == 'all'
53
54
  Requires-Dist: psutil>=6.0.0; extra == 'all'
54
55
  Requires-Dist: pyjwt>=2.12.1; extra == 'all'
@@ -96,6 +97,8 @@ Requires-Dist: taskiq>=0.11.0; extra == 'tasks'
96
97
  Provides-Extra: upload
97
98
  Requires-Dist: aiofiles>=24.1.0; extra == 'upload'
98
99
  Requires-Dist: python-multipart>=0.0.12; extra == 'upload'
100
+ Provides-Extra: vision
101
+ Requires-Dist: ort-vision-sdk>=0.4.0; extra == 'vision'
99
102
  Provides-Extra: webpush
100
103
  Requires-Dist: cryptography>=42.0.0; extra == 'webpush'
101
104
  Requires-Dist: pywebpush>=2.0.0; extra == 'webpush'
@@ -219,6 +222,7 @@ Feature-rich helpers pull in third-party dependencies that you only need when yo
219
222
  | `[http]` | `httpx` | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, OAuth2 / OIDC providers |
220
223
  | `[prometheus]` | `prometheus-client` | `PrometheusMiddleware`, `make_prometheus_router`, `make_prometheus_registry` |
221
224
  | `[mfa]` | `pyotp` | `TOTPHelper` + MFA/2FA endpoints on the bundled auth flow |
225
+ | `[vision]` | `ort-vision-sdk` | `Detector` / `Classifier` / `Segmenter` (ONNX) + prediction schemas |
222
226
  | `[otel]` | `opentelemetry-sdk` + OTLP/gRPC exporter + FastAPI/SQLAlchemy/httpx instrumentors | `setup_tracing` — distributed tracing |
223
227
  | `[sqlite]` | `aiosqlite` | SQLite async driver for `sqlite+aiosqlite://` URLs (dev default) |
224
228
  | `[postgres]` | `asyncpg` | PostgreSQL async driver for `postgresql+asyncpg://` URLs (production) |
@@ -259,10 +263,11 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
259
263
  | `tempest_fastapi_sdk.utils.http_client` *(extra: `[http]`)* | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, `REQUEST_ID_HEADER` — typed httpx wrapper |
260
264
  | `tempest_fastapi_sdk.utils.storage_backends` *(extra: `[upload]`)* | `UploadStorage` protocol, `LocalUploadStorage`, `MinIOUploadStorage`, `UploadResult`, `ContentValidator` |
261
265
  | `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `AsyncTaskBrokerManager` (TaskIQ lifecycle wrapper), `AsyncTaskScheduler` (periodic / cron tasks) |
266
+ | `tempest_fastapi_sdk.vision` *(extra: `[vision]`)* | `Detector`, `Classifier`, `Segmenter` (ONNX, lazy), `DetectionSchema`/`ClassificationSchema`/`SegmentationSchema`/`BoundingBoxSchema`/`ClassProbabilitySchema`, `to_detection_schemas`/`to_classification_schema`/`to_segmentation_schemas` |
262
267
  | `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField` — old names without the suffix kept as deprecated aliases — `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
263
268
  | `tempest_fastapi_sdk.cli` | `tempest` console script — `new <name>` (scaffold layered service), `lint` / `format` / `fmt-check` / `type` / `test` / `check` (run preferred quality gates), `version` / `--version` |
264
269
 
265
- Core primitives are re-exported from `tempest_fastapi_sdk` at the top level — `from tempest_fastapi_sdk import BaseModel, BaseRepository, AppException` always works. The extras-gated managers in `tempest_fastapi_sdk.cache`, `tempest_fastapi_sdk.queue` and `tempest_fastapi_sdk.tasks` must be imported from their own submodule (`from tempest_fastapi_sdk.queue import AsyncBrokerManager`).
270
+ Core primitives are re-exported from `tempest_fastapi_sdk` at the top level — `from tempest_fastapi_sdk import BaseModel, BaseRepository, AppException` always works. The extras-gated managers in `tempest_fastapi_sdk.cache`, `tempest_fastapi_sdk.queue`, `tempest_fastapi_sdk.tasks` and `tempest_fastapi_sdk.vision` must be imported from their own submodule (`from tempest_fastapi_sdk.queue import AsyncBrokerManager`).
266
271
 
267
272
  ---
268
273
 
@@ -3314,62 +3319,66 @@ app.mount(
3314
3319
  )
3315
3320
  ```
3316
3321
 
3317
- For cookie-based session flows, `set_cookie` / `clear_cookie` write headers that already include the safe combo (`HttpOnly`, `Secure`, `SameSite=Lax`) so the caller only picks the bits they want to deviate from. `SameSite` is a `BaseStrEnum` (`SameSite.LAX` / `STRICT` / `NONE`) using `SameSite.NONE` forces `Secure=True` to honor the browser requirement.
3322
+ For cookie-based session flows, `set_cookie` / `clear_cookie` write headers that already include the safe combo (`HttpOnly`, `Secure`, `SameSite=Lax`) so the caller only picks the bits they want to deviate from. `SameSite` is a **type alias** `Literal["lax", "strict", "none"]` — pass the literal string, not an enum. The SDK does **not** auto-force `Secure` for `samesite="none"`: pass `samesite="none", secure=True` yourself in cross-site scenarios (the browser rejects `SameSite=None` without `Secure`).
3318
3323
 
3319
3324
  ```python
3320
3325
  from fastapi import Response
3321
3326
 
3322
- from tempest_fastapi_sdk import SameSite, clear_cookie, set_cookie
3327
+ from tempest_fastapi_sdk import clear_cookie, set_cookie
3323
3328
 
3324
3329
 
3325
3330
  def login(response: Response, token: str) -> None:
3326
3331
  set_cookie(
3327
3332
  response,
3328
- key="session",
3329
- value=token,
3333
+ "session", # name (positional)
3334
+ token, # value (positional)
3330
3335
  max_age=3600,
3331
- same_site=SameSite.LAX, # default
3332
- # secure=True, # auto-enabled for SameSite.NONE
3333
- # http_only=True, # default
3336
+ samesite="lax", # "lax" (default), "strict" or "none"
3337
+ # secure=True, # default — set False only for local HTTP
3338
+ # http_only=True, # default
3334
3339
  path="/",
3335
3340
  )
3336
3341
 
3337
3342
 
3338
3343
  def logout(response: Response) -> None:
3339
- clear_cookie(response, key="session", path="/")
3344
+ clear_cookie(response, "session", path="/")
3340
3345
  ```
3341
3346
 
3342
3347
  ### Brute-force throttling recipe
3343
3348
 
3344
- `AttemptThrottle` counts failed attempts per key (typically `<endpoint>:<identifier>` — login email, password-reset target, etc.) and either yields a free attempt, locks the caller for a cooldown, or signals "back off" once the threshold is crossed. Two backends ship: `MemoryThrottleBackend` (defaults — process-local, perfect for tests and single-process services) and `RedisThrottleBackend` (multi-process / multi-host deployments).
3349
+ `AttemptThrottle` counts failed attempts per key (typically `<endpoint>:<identifier>` — login email, password-reset target, IP, etc.). The constructor takes a `backend` any object matching the `ThrottleBackend` Protocol (`get`/`incr`/`expire`/`ttl`/`delete`), which `redis.asyncio.Redis` satisfies out of the box plus `max_attempts` + `window_seconds`. No in-memory backend is bundled: pass the Redis client from `AsyncRedisManager` (or a [fakeredis](https://github.com/cunla/fakeredis-py) double in tests).
3345
3350
 
3346
3351
  ```python
3347
- from tempest_fastapi_sdk import AttemptThrottle, ThrottleStatus, TooManyRequestsException
3348
- from tempest_fastapi_sdk.utils.throttle import RedisThrottleBackend
3352
+ from tempest_fastapi_sdk import AttemptThrottle, UnauthorizedException
3353
+ from tempest_fastapi_sdk.cache import AsyncRedisManager
3354
+
3355
+ from src.core.settings import settings
3349
3356
 
3357
+ cache = AsyncRedisManager(settings.REDIS_URL)
3358
+ # cache.client is redis.asyncio.Redis — matches the ThrottleBackend Protocol
3350
3359
  throttle = AttemptThrottle(
3351
- backend=RedisThrottleBackend(redis_manager=cache),
3360
+ cache.client,
3352
3361
  max_attempts=5,
3353
- window_seconds=300, # rolling window
3354
- lock_seconds=900, # cooldown applied when threshold trips
3362
+ window_seconds=300, # fixed window; also the TTL on the first failure
3363
+ namespace="login", # key prefix so multiple throttles can coexist
3364
+ fail_open=True, # a Redis outage degrades to "allow", never locks everyone out
3355
3365
  )
3356
3366
 
3357
3367
 
3358
3368
  async def login(email: str, password: str) -> User:
3359
- status = await throttle.check(f"login:{email}")
3360
- if status is ThrottleStatus.LOCKED:
3361
- raise TooManyRequestsException(message="Too many attempts; try again later.")
3369
+ key = f"login:{email}"
3370
+ await throttle.raise_if_blocked(key) # raises 429 when over budget
3362
3371
 
3363
- user = await users_repo.get_by_email(email)
3364
- if not password_utils.verify(password, user.password_hash):
3365
- await throttle.record_failure(f"login:{email}")
3372
+ user = await users_repo.get_or_none({"email": email})
3373
+ if user is None or not password_utils.verify(password, user.hashed_password):
3374
+ await throttle.hit(key) # +1 failure, applies the TTL
3366
3375
  raise UnauthorizedException(message="Invalid credentials.")
3367
3376
 
3368
- await throttle.reset(f"login:{email}")
3377
+ await throttle.reset(key) # success clears the counter
3369
3378
  return user
3370
3379
  ```
3371
3380
 
3372
- `check()` returns a `ThrottleStatus` enum (`ALLOWED` / `LOCKED`); inspecting `.attempts_left` and `.retry_after_seconds` on the result lets you surface friendly error payloads. Pair with `TooManyRequestsException` so the SDK exception handler emits the canonical `{detail, code, details}` envelope with HTTP 429 and a `Retry-After` header.
3381
+ `throttle.status(key)` (peek without incrementing) and `throttle.hit(key)` (increment) both return a frozen `ThrottleStatus` dataclass `attempts: int`, `blocked: bool`, `retry_after_seconds: int` to build friendly error payloads. `raise_if_blocked` already raises `TooManyRequestsException`, which the SDK exception handler turns into the canonical `{detail, code, details}` envelope with HTTP 429 and a `Retry-After` header.
3373
3382
 
3374
3383
  ### Opaque tokens recipe
3375
3384
 
@@ -3408,7 +3417,7 @@ async def consume_reset_token(plain: str, user_id: UUID) -> bool:
3408
3417
 
3409
3418
  ### Client IP extraction recipe
3410
3419
 
3411
- `get_client_ip(request)` and `get_client_ip_from_scope(scope)` return the real client IP behind an arbitrary chain of proxies. They inspect `Forwarded` (RFC 7239) first, fall back to `X-Forwarded-For` honoring an explicit `trusted_proxies` allowlist, and finally use the raw socket address never naively trusting an inbound header.
3420
+ `get_client_ip(request)` and `get_client_ip_from_scope(scope)` return the real client IP behind a proxy. By design they accept **one** trusted header name (`trusted_header=`) that your edge proxy is known to set (e.g. `"x-real-ip"` on Nginx) without it, they use the direct peer address. Anti-spoofing belongs at the proxy (which overwrites the header with the real peer), not in Python, so the SDK only reads the header you declare trusted.
3412
3421
 
3413
3422
  ```python
3414
3423
  from fastapi import Request
@@ -3418,15 +3427,13 @@ from tempest_fastapi_sdk import get_client_ip
3418
3427
 
3419
3428
  @router.post("/login")
3420
3429
  async def login(request: Request, payload: LoginIn) -> LoginOut:
3421
- ip = get_client_ip(
3422
- request,
3423
- trusted_proxies={"10.0.0.0/8", "192.168.0.0/16"},
3424
- )
3425
- await throttle.check(f"login:{ip}")
3430
+ # Behind Nginx that overwrites X-Real-IP with the real peer:
3431
+ ip = get_client_ip(request, trusted_header="x-real-ip")
3432
+ await throttle.raise_if_blocked(f"login:{ip}")
3426
3433
  ...
3427
3434
  ```
3428
3435
 
3429
- Use `get_client_ip_from_scope(scope)` from middleware or websocket handlers where only the ASGI scope is in reach. Both helpers normalize IPv6 brackets and refuse to return private addresses when `accept_private=False` is passed handy when only public traffic should ever populate audit logs.
3436
+ Use `get_client_ip_from_scope(scope, trusted_header=...)` from middleware or websocket handlers where only the ASGI scope is in reach. If you expose the app directly to the internet, omit `trusted_header=` so the peer address is used.
3430
3437
 
3431
3438
  ### Command-line interface recipe
3432
3439
 
@@ -116,6 +116,7 @@ Feature-rich helpers pull in third-party dependencies that you only need when yo
116
116
  | `[http]` | `httpx` | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, OAuth2 / OIDC providers |
117
117
  | `[prometheus]` | `prometheus-client` | `PrometheusMiddleware`, `make_prometheus_router`, `make_prometheus_registry` |
118
118
  | `[mfa]` | `pyotp` | `TOTPHelper` + MFA/2FA endpoints on the bundled auth flow |
119
+ | `[vision]` | `ort-vision-sdk` | `Detector` / `Classifier` / `Segmenter` (ONNX) + prediction schemas |
119
120
  | `[otel]` | `opentelemetry-sdk` + OTLP/gRPC exporter + FastAPI/SQLAlchemy/httpx instrumentors | `setup_tracing` — distributed tracing |
120
121
  | `[sqlite]` | `aiosqlite` | SQLite async driver for `sqlite+aiosqlite://` URLs (dev default) |
121
122
  | `[postgres]` | `asyncpg` | PostgreSQL async driver for `postgresql+asyncpg://` URLs (production) |
@@ -156,10 +157,11 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
156
157
  | `tempest_fastapi_sdk.utils.http_client` *(extra: `[http]`)* | `HTTPClient`, `RetryPolicy`, `CircuitOpenError`, `REQUEST_ID_HEADER` — typed httpx wrapper |
157
158
  | `tempest_fastapi_sdk.utils.storage_backends` *(extra: `[upload]`)* | `UploadStorage` protocol, `LocalUploadStorage`, `MinIOUploadStorage`, `UploadResult`, `ContentValidator` |
158
159
  | `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `AsyncTaskBrokerManager` (TaskIQ lifecycle wrapper), `AsyncTaskScheduler` (periodic / cron tasks) |
160
+ | `tempest_fastapi_sdk.vision` *(extra: `[vision]`)* | `Detector`, `Classifier`, `Segmenter` (ONNX, lazy), `DetectionSchema`/`ClassificationSchema`/`SegmentationSchema`/`BoundingBoxSchema`/`ClassProbabilitySchema`, `to_detection_schemas`/`to_classification_schema`/`to_segmentation_schemas` |
159
161
  | `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField` — old names without the suffix kept as deprecated aliases — `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
160
162
  | `tempest_fastapi_sdk.cli` | `tempest` console script — `new <name>` (scaffold layered service), `lint` / `format` / `fmt-check` / `type` / `test` / `check` (run preferred quality gates), `version` / `--version` |
161
163
 
162
- Core primitives are re-exported from `tempest_fastapi_sdk` at the top level — `from tempest_fastapi_sdk import BaseModel, BaseRepository, AppException` always works. The extras-gated managers in `tempest_fastapi_sdk.cache`, `tempest_fastapi_sdk.queue` and `tempest_fastapi_sdk.tasks` must be imported from their own submodule (`from tempest_fastapi_sdk.queue import AsyncBrokerManager`).
164
+ Core primitives are re-exported from `tempest_fastapi_sdk` at the top level — `from tempest_fastapi_sdk import BaseModel, BaseRepository, AppException` always works. The extras-gated managers in `tempest_fastapi_sdk.cache`, `tempest_fastapi_sdk.queue`, `tempest_fastapi_sdk.tasks` and `tempest_fastapi_sdk.vision` must be imported from their own submodule (`from tempest_fastapi_sdk.queue import AsyncBrokerManager`).
163
165
 
164
166
  ---
165
167
 
@@ -3211,62 +3213,66 @@ app.mount(
3211
3213
  )
3212
3214
  ```
3213
3215
 
3214
- For cookie-based session flows, `set_cookie` / `clear_cookie` write headers that already include the safe combo (`HttpOnly`, `Secure`, `SameSite=Lax`) so the caller only picks the bits they want to deviate from. `SameSite` is a `BaseStrEnum` (`SameSite.LAX` / `STRICT` / `NONE`) using `SameSite.NONE` forces `Secure=True` to honor the browser requirement.
3216
+ For cookie-based session flows, `set_cookie` / `clear_cookie` write headers that already include the safe combo (`HttpOnly`, `Secure`, `SameSite=Lax`) so the caller only picks the bits they want to deviate from. `SameSite` is a **type alias** `Literal["lax", "strict", "none"]` — pass the literal string, not an enum. The SDK does **not** auto-force `Secure` for `samesite="none"`: pass `samesite="none", secure=True` yourself in cross-site scenarios (the browser rejects `SameSite=None` without `Secure`).
3215
3217
 
3216
3218
  ```python
3217
3219
  from fastapi import Response
3218
3220
 
3219
- from tempest_fastapi_sdk import SameSite, clear_cookie, set_cookie
3221
+ from tempest_fastapi_sdk import clear_cookie, set_cookie
3220
3222
 
3221
3223
 
3222
3224
  def login(response: Response, token: str) -> None:
3223
3225
  set_cookie(
3224
3226
  response,
3225
- key="session",
3226
- value=token,
3227
+ "session", # name (positional)
3228
+ token, # value (positional)
3227
3229
  max_age=3600,
3228
- same_site=SameSite.LAX, # default
3229
- # secure=True, # auto-enabled for SameSite.NONE
3230
- # http_only=True, # default
3230
+ samesite="lax", # "lax" (default), "strict" or "none"
3231
+ # secure=True, # default — set False only for local HTTP
3232
+ # http_only=True, # default
3231
3233
  path="/",
3232
3234
  )
3233
3235
 
3234
3236
 
3235
3237
  def logout(response: Response) -> None:
3236
- clear_cookie(response, key="session", path="/")
3238
+ clear_cookie(response, "session", path="/")
3237
3239
  ```
3238
3240
 
3239
3241
  ### Brute-force throttling recipe
3240
3242
 
3241
- `AttemptThrottle` counts failed attempts per key (typically `<endpoint>:<identifier>` — login email, password-reset target, etc.) and either yields a free attempt, locks the caller for a cooldown, or signals "back off" once the threshold is crossed. Two backends ship: `MemoryThrottleBackend` (defaults — process-local, perfect for tests and single-process services) and `RedisThrottleBackend` (multi-process / multi-host deployments).
3243
+ `AttemptThrottle` counts failed attempts per key (typically `<endpoint>:<identifier>` — login email, password-reset target, IP, etc.). The constructor takes a `backend` any object matching the `ThrottleBackend` Protocol (`get`/`incr`/`expire`/`ttl`/`delete`), which `redis.asyncio.Redis` satisfies out of the box plus `max_attempts` + `window_seconds`. No in-memory backend is bundled: pass the Redis client from `AsyncRedisManager` (or a [fakeredis](https://github.com/cunla/fakeredis-py) double in tests).
3242
3244
 
3243
3245
  ```python
3244
- from tempest_fastapi_sdk import AttemptThrottle, ThrottleStatus, TooManyRequestsException
3245
- from tempest_fastapi_sdk.utils.throttle import RedisThrottleBackend
3246
+ from tempest_fastapi_sdk import AttemptThrottle, UnauthorizedException
3247
+ from tempest_fastapi_sdk.cache import AsyncRedisManager
3248
+
3249
+ from src.core.settings import settings
3246
3250
 
3251
+ cache = AsyncRedisManager(settings.REDIS_URL)
3252
+ # cache.client is redis.asyncio.Redis — matches the ThrottleBackend Protocol
3247
3253
  throttle = AttemptThrottle(
3248
- backend=RedisThrottleBackend(redis_manager=cache),
3254
+ cache.client,
3249
3255
  max_attempts=5,
3250
- window_seconds=300, # rolling window
3251
- lock_seconds=900, # cooldown applied when threshold trips
3256
+ window_seconds=300, # fixed window; also the TTL on the first failure
3257
+ namespace="login", # key prefix so multiple throttles can coexist
3258
+ fail_open=True, # a Redis outage degrades to "allow", never locks everyone out
3252
3259
  )
3253
3260
 
3254
3261
 
3255
3262
  async def login(email: str, password: str) -> User:
3256
- status = await throttle.check(f"login:{email}")
3257
- if status is ThrottleStatus.LOCKED:
3258
- raise TooManyRequestsException(message="Too many attempts; try again later.")
3263
+ key = f"login:{email}"
3264
+ await throttle.raise_if_blocked(key) # raises 429 when over budget
3259
3265
 
3260
- user = await users_repo.get_by_email(email)
3261
- if not password_utils.verify(password, user.password_hash):
3262
- await throttle.record_failure(f"login:{email}")
3266
+ user = await users_repo.get_or_none({"email": email})
3267
+ if user is None or not password_utils.verify(password, user.hashed_password):
3268
+ await throttle.hit(key) # +1 failure, applies the TTL
3263
3269
  raise UnauthorizedException(message="Invalid credentials.")
3264
3270
 
3265
- await throttle.reset(f"login:{email}")
3271
+ await throttle.reset(key) # success clears the counter
3266
3272
  return user
3267
3273
  ```
3268
3274
 
3269
- `check()` returns a `ThrottleStatus` enum (`ALLOWED` / `LOCKED`); inspecting `.attempts_left` and `.retry_after_seconds` on the result lets you surface friendly error payloads. Pair with `TooManyRequestsException` so the SDK exception handler emits the canonical `{detail, code, details}` envelope with HTTP 429 and a `Retry-After` header.
3275
+ `throttle.status(key)` (peek without incrementing) and `throttle.hit(key)` (increment) both return a frozen `ThrottleStatus` dataclass `attempts: int`, `blocked: bool`, `retry_after_seconds: int` to build friendly error payloads. `raise_if_blocked` already raises `TooManyRequestsException`, which the SDK exception handler turns into the canonical `{detail, code, details}` envelope with HTTP 429 and a `Retry-After` header.
3270
3276
 
3271
3277
  ### Opaque tokens recipe
3272
3278
 
@@ -3305,7 +3311,7 @@ async def consume_reset_token(plain: str, user_id: UUID) -> bool:
3305
3311
 
3306
3312
  ### Client IP extraction recipe
3307
3313
 
3308
- `get_client_ip(request)` and `get_client_ip_from_scope(scope)` return the real client IP behind an arbitrary chain of proxies. They inspect `Forwarded` (RFC 7239) first, fall back to `X-Forwarded-For` honoring an explicit `trusted_proxies` allowlist, and finally use the raw socket address never naively trusting an inbound header.
3314
+ `get_client_ip(request)` and `get_client_ip_from_scope(scope)` return the real client IP behind a proxy. By design they accept **one** trusted header name (`trusted_header=`) that your edge proxy is known to set (e.g. `"x-real-ip"` on Nginx) without it, they use the direct peer address. Anti-spoofing belongs at the proxy (which overwrites the header with the real peer), not in Python, so the SDK only reads the header you declare trusted.
3309
3315
 
3310
3316
  ```python
3311
3317
  from fastapi import Request
@@ -3315,15 +3321,13 @@ from tempest_fastapi_sdk import get_client_ip
3315
3321
 
3316
3322
  @router.post("/login")
3317
3323
  async def login(request: Request, payload: LoginIn) -> LoginOut:
3318
- ip = get_client_ip(
3319
- request,
3320
- trusted_proxies={"10.0.0.0/8", "192.168.0.0/16"},
3321
- )
3322
- await throttle.check(f"login:{ip}")
3324
+ # Behind Nginx that overwrites X-Real-IP with the real peer:
3325
+ ip = get_client_ip(request, trusted_header="x-real-ip")
3326
+ await throttle.raise_if_blocked(f"login:{ip}")
3323
3327
  ...
3324
3328
  ```
3325
3329
 
3326
- Use `get_client_ip_from_scope(scope)` from middleware or websocket handlers where only the ASGI scope is in reach. Both helpers normalize IPv6 brackets and refuse to return private addresses when `accept_private=False` is passed handy when only public traffic should ever populate audit logs.
3330
+ Use `get_client_ip_from_scope(scope, trusted_header=...)` from middleware or websocket handlers where only the ASGI scope is in reach. If you expose the app directly to the internet, omit `trusted_header=` so the peer address is used.
3327
3331
 
3328
3332
  ### Command-line interface recipe
3329
3333