tempest-fastapi-sdk 0.90.0__tar.gz → 0.92.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/CHANGELOG.md +106 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/CLAUDE.md +26 -11
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/PKG-INFO +10 -7
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/README.md +9 -6
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/migration.en.md +30 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/migration.md +30 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/auth-flow.en.md +49 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/auth-flow.md +49 -0
- tempest_fastapi_sdk-0.92.0/docs/recipes/sse.en.md +390 -0
- tempest_fastapi_sdk-0.92.0/docs/recipes/sse.md +390 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/pyproject.toml +1 -1
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/__init__.py +15 -1
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/dependencies/auth.py +38 -7
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/__init__.py +22 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/locale.py +24 -4
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/router.py +240 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/schemas.py +223 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/service.py +423 -1
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_change.html +20 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_change_error.html +27 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_change_success.html +23 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_changed_notice.html +10 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_verification.html +19 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_verification_error.html +26 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/en-US/email_verification_success.html +23 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_change.html +20 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_error.html +27 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_success.html +23 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_changed_notice.html +10 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification.html +19 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_error.html +26 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_success.html +23 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_token_model.py +18 -2
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/settings/mixins.py +138 -0
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/sse/__init__.py +23 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sse/broker.py +53 -2
- tempest_fastapi_sdk-0.92.0/tempest_fastapi_sdk/sse/event_stream.py +368 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_jwt_dependency.py +75 -0
- tempest_fastapi_sdk-0.92.0/tests/auth/test_email_change.py +472 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sse/test_broker.py +35 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sse/test_event_stream.py +98 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/uv.lock +1 -1
- tempest_fastapi_sdk-0.90.0/docs/recipes/sse.en.md +0 -226
- tempest_fastapi_sdk-0.90.0/docs/recipes/sse.md +0 -226
- tempest_fastapi_sdk-0.90.0/tempest_fastapi_sdk/sse/__init__.py +0 -15
- tempest_fastapi_sdk-0.90.0/tempest_fastapi_sdk/sse/event_stream.py +0 -205
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.github/workflows/ci.yml +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.github/workflows/docs.yml +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.github/workflows/release-pypi.yml +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.gitignore +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/.python-version +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/Makefile +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/architecture.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/architecture.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/changelog.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/changelog.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/contributing.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/contributing.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/index.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/index.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/installation.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/installation.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/index.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/index.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/api.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/api.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/business-rules.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/business-rules.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/domain.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/domain.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/flows.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/flows.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/index.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/learning/marketplace/index.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/admin.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/admin.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/audit-trail.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/audit-trail.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/br-helpers.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/br-helpers.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cache.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cache.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cli.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/cli.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/database.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/database.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/deploy-safety.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/deploy-safety.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/downloads.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/downloads.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/email.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/email.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/feature-flags.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/feature-flags.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/fields.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/fields.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/file-store.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/file-store.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http-client.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http-client.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/http.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/idempotency.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/idempotency.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/index.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/index.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/logging.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/logging.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/metrics.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/metrics.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/mfa.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/mfa.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/multi-tenant.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/multi-tenant.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/observability.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/observability.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/offline-sync.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/offline-sync.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/outbox.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/outbox.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/queue-tasks.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/queue-tasks.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/realtime.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/realtime.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/refresh-tokens.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/refresh-tokens.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/security.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/security.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/sessions.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/sessions.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/storage.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/storage.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/stored-files.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/stored-files.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/testing.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/testing.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/typing.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/typing.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/uploads.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/uploads.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/utilities.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/utilities.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/vision.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/vision.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/webpush.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/webpush.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/websocket.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/recipes/websocket.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/reference.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/reference.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/roadmap.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/roadmap.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/ssr.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/ssr.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/tutorial.en.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/docs/tutorial.md +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/mkdocs.yml +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/mkdocs_hooks/llmstxt.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/scripts/extract_recipe.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/actions.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/config.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/discovery.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/session.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/site.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/admin/theme.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/server.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/static.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/auth/token_delivery.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/Dockerfile.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/dockerignore.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/config.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/db.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/main.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/new.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/cli/user.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/context.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/enums.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/logging.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/core/typed.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/audit.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/backup.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/connection.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/model.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/repository.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/user_refresh_token_model.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/db/webpush_subscription_model.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/flags/service.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/py.typed +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/services/base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/services/file_mixin.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/settings/base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/_static/htmx.min.js +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/assets.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/page.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/ssr/response.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/testing/database.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/download.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/email.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/fields.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/file_store.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/log.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/password.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/vision/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/vision/mapping.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/vision/schemas.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/webpush/service.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_actions.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_auth.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_discovery.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_forms.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_logs_nav.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_mfa.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_rich_filters.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_site.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_theme.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_upload_field.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/admin/test_user_model.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_body_size.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_cookies.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_cors.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_csrf.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_dependencies_auth.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_graceful.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_handlers.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_health_router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_idempotency.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_logs_router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_oauth.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_prometheus.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_rate_limit.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_rate_limit_extras.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_request_id_middleware.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_role_dependency.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_server.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_static.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_tool_spec.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_tracing.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_webhooks.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/api/test_webhooks_rsa.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_cookie_delivery.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_guards.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_locale.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_mfa.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_refresh.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_refresh_db.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/auth/test_service.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/test_decorator.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/test_invalidation.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cache/test_redis_manager.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_config.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_db.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_db_seed.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_docker_compose.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_generate.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_lint_strictness.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_main.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_secrets.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/cli/test_user.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/conftest.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/controllers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/controllers/test_base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_context.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_enums.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_logging.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/core/test_typed.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_alembic_hooks.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_audit.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_backup.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_bulk_ops.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_connection.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_migrations.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_mixins.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_model.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_outbox.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_repository.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_safe_upgrade.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_slow_query.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/db/test_tenant.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/exceptions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/exceptions/test_exceptions.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/exceptions/test_i18n.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/flags/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/flags/test_flags.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/queue/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/queue/test_manager.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_cursor_pagination.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_link_headers.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_pagination.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/schemas/test_response.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/services/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/services/test_base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/services/test_file_mixin.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sessions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sessions/test_sessions.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/settings/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/settings/test_base.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/settings/test_mixins.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/sse/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/test_integration.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/test_page.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/ssr/test_response.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/storage/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/storage/test_minio_client.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/tasks/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/tasks/test_manager.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/tasks/test_scheduler.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/testing/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/testing/test_database.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_client_ip.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_datetime.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_dict.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_download.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_email.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_fields.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_file_store.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_http_client.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_jwt.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_lazy_extras.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_locations.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_log.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_metrics.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_opaque_token.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_password.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_regex.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_storage_backends.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_throttle.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/utils/test_upload.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/vision/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/vision/test_vision.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_dispatcher.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_router.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_schemas.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/webpush/test_service.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/websockets/__init__.py +0 -0
- {tempest_fastapi_sdk-0.90.0 → tempest_fastapi_sdk-0.92.0}/tests/websockets/test_hub_and_router.py +0 -0
|
@@ -5,6 +5,112 @@ All notable changes to **tempest-fastapi-sdk** are listed below.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.92.0] — 2026-07-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Email change / re-verification / recovery flow** on `UserAuthService`
|
|
13
|
+
+ `make_auth_router`, mirroring the password reset/change surface:
|
|
14
|
+
- **Change email (authenticated)** — `request_email_change` (verifies
|
|
15
|
+
the current password, stages the new address, emails a confirmation
|
|
16
|
+
link to the NEW address) + `confirm_email_change` (consumes the
|
|
17
|
+
token, flips the email, and — when `AUTH_EMAIL_CHANGE_NOTIFY_OLD`
|
|
18
|
+
is on — sends a security notice to the OLD address). Routes:
|
|
19
|
+
`POST /auth/email-change/request` (202) and
|
|
20
|
+
`POST /auth/email-change/confirm`.
|
|
21
|
+
- **Re-verify current email** — `request_email_verification` /
|
|
22
|
+
`confirm_email_verification` (resend a verification link to the
|
|
23
|
+
current address; confirming marks the account active). Routes:
|
|
24
|
+
`POST /auth/email-verify/request` (202) and
|
|
25
|
+
`POST /auth/email-verify/confirm`.
|
|
26
|
+
- **Recovery (lost mailbox access)** — `request_email_recovery`, an
|
|
27
|
+
**unauthenticated** entry point that proves identity with the
|
|
28
|
+
account password **plus a valid MFA code when TOTP is enrolled**,
|
|
29
|
+
then emails the confirmation link to the new address. Always returns
|
|
30
|
+
a generic `202` for soft failures (unknown email, wrong password,
|
|
31
|
+
bad/missing MFA code) so it can't enumerate accounts. Route
|
|
32
|
+
`POST /auth/email-recovery/request` is **opt-in** via
|
|
33
|
+
`AUTH_EMAIL_RECOVERY_ENABLED` (off by default).
|
|
34
|
+
- **Old-email security notice** on a confirmed change, toggled by
|
|
35
|
+
`AUTH_EMAIL_CHANGE_NOTIFY_OLD` (default `True`).
|
|
36
|
+
- **Backend HTML pages** (when `AUTH_BACKEND_LINKS=True`):
|
|
37
|
+
`GET /auth/email-change/{token}` and `GET /auth/email-verify/{token}`
|
|
38
|
+
render self-contained success/error pages — no frontend needed.
|
|
39
|
+
- New schemas exported from the package root:
|
|
40
|
+
`EmailChangeRequestSchema`, `EmailChangeConfirmSchema`,
|
|
41
|
+
`EmailRecoveryRequestSchema`, `EmailChangeResponseSchema`,
|
|
42
|
+
`EmailChangeToken`, `EmailVerificationToken`.
|
|
43
|
+
- New `UserTokenPurpose.EMAIL_CHANGE`; the existing
|
|
44
|
+
`EMAIL_VERIFICATION` purpose now backs the re-verify flow.
|
|
45
|
+
- 14 bundled bilingual templates (PT-BR + EN-US): `email_change.html`,
|
|
46
|
+
`email_verification.html`, `email_changed_notice.html`, plus
|
|
47
|
+
`email_change_success/error.html` and
|
|
48
|
+
`email_verification_success/error.html`.
|
|
49
|
+
- Localized subjects/bodies for the three new emails.
|
|
50
|
+
- New settings: `AUTH_EMAIL_CHANGE_TTL_SECONDS`,
|
|
51
|
+
`AUTH_EMAIL_VERIFICATION_TTL_SECONDS`,
|
|
52
|
+
`AUTH_EMAIL_CHANGE_URL_TEMPLATE`,
|
|
53
|
+
`AUTH_EMAIL_VERIFICATION_URL_TEMPLATE`, `AUTH_EMAIL_CHANGE_TEMPLATE`,
|
|
54
|
+
`AUTH_EMAIL_VERIFICATION_TEMPLATE`,
|
|
55
|
+
`AUTH_EMAIL_CHANGED_NOTICE_TEMPLATE`, `AUTH_EMAIL_CHANGE_NOTIFY_OLD`,
|
|
56
|
+
`AUTH_EMAIL_RECOVERY_ENABLED`, `AUTH_EMAIL_CHANGE_SUCCESS_TEMPLATE`,
|
|
57
|
+
`AUTH_EMAIL_CHANGE_ERROR_TEMPLATE`,
|
|
58
|
+
`AUTH_EMAIL_VERIFICATION_SUCCESS_TEMPLATE`,
|
|
59
|
+
`AUTH_EMAIL_VERIFICATION_ERROR_TEMPLATE`.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- **`BaseUserTokenModel` gains a nullable `payload` column**
|
|
64
|
+
(`VARCHAR(320)`) carrying flow context — the pending new email for an
|
|
65
|
+
`EMAIL_CHANGE` token. **Requires a migration** in consuming projects
|
|
66
|
+
(additive nullable column, safe). See the migration guide.
|
|
67
|
+
|
|
68
|
+
## [0.91.0] — 2026-07-05
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- **SSE backpressure — bounded queue + overflow policy.**
|
|
73
|
+
`EventStream` (and `SSEBroker`-created streams) now cap the buffered
|
|
74
|
+
events at `max_queue` (default `1000`) instead of growing without
|
|
75
|
+
limit when a client stalls. When the buffer fills, `overflow` decides
|
|
76
|
+
what gives:
|
|
77
|
+
- `"drop_oldest"` (default) — evict the stalest event, keep the
|
|
78
|
+
freshest data.
|
|
79
|
+
- `"drop_newest"` — discard the incoming event, keep the backlog.
|
|
80
|
+
- `"block"` — apply real backpressure (the producer waits for a slot).
|
|
81
|
+
`EventStream.dropped_events` counts events lost to overflow for
|
|
82
|
+
metrics / logs. `max_queue=0` restores the pre-0.91 unbounded
|
|
83
|
+
behavior. The `close()` sentinel is never dropped or blocked, so a
|
|
84
|
+
stream can always terminate. `SSEBroker(max_queue=..., overflow=...)`
|
|
85
|
+
applies the same policy to every stream it opens.
|
|
86
|
+
- **SSE lifecycle helpers — no more hand-rolled `try/finally`.**
|
|
87
|
+
- `sse_response(..., on_disconnect=...)` runs a cleanup callback
|
|
88
|
+
(awaited if a coroutine) when the client disconnects or the stream
|
|
89
|
+
ends — the one place guaranteed to fire — so a bound producer task
|
|
90
|
+
is cancelled or a channel unregistered without boilerplate.
|
|
91
|
+
- `EventStream.response(*, on_disconnect=..., status_code=...,
|
|
92
|
+
headers=...)` wraps `stream()` in an SSE response in one call.
|
|
93
|
+
- `SSEBroker.response(channel, ...)` bundles the whole per-connection
|
|
94
|
+
lifecycle: `register` + `sse_response` + `unregister`-on-disconnect.
|
|
95
|
+
This removes the leak-prone manual wrapper the recipe used to need.
|
|
96
|
+
- **JWT via query string for cookieless clients.**
|
|
97
|
+
`make_bearer_token_dependency` and `make_jwt_user_dependency` gained a
|
|
98
|
+
`query_param` argument (e.g. `query_param="access_token"`). Token
|
|
99
|
+
lookup order becomes header → cookie → query string. This unblocks
|
|
100
|
+
browser `EventSource` (SSE), whose constructor accepts neither headers
|
|
101
|
+
nor a body. Documented with a security warning: use short-lived access
|
|
102
|
+
tokens only, over TLS, and scrub the value from access logs. Prefer a
|
|
103
|
+
session cookie (`withCredentials`) whenever the client shares the
|
|
104
|
+
API's origin.
|
|
105
|
+
- **`OverflowPolicy`** is exported from `tempest_fastapi_sdk.sse` and the
|
|
106
|
+
package root.
|
|
107
|
+
|
|
108
|
+
### Fixed
|
|
109
|
+
|
|
110
|
+
- `tempest_fastapi_sdk/sse/__init__.py` re-exports now use the explicit
|
|
111
|
+
`X as X` alias form required by the repo's re-export convention (was a
|
|
112
|
+
structural defect flagged by strict type-checkers).
|
|
113
|
+
|
|
8
114
|
## [0.90.0] — 2026-07-04
|
|
9
115
|
|
|
10
116
|
### Added
|
|
@@ -55,16 +55,26 @@ without the docs being green.
|
|
|
55
55
|
|
|
56
56
|
The SDK currently covers (Sep 2025+, post-v0.31.x):
|
|
57
57
|
|
|
58
|
-
- **Auth** — JWT/bearer/role/permission/X-Token deps
|
|
58
|
+
- **Auth** — JWT/bearer/role/permission/X-Token deps (JWT deps
|
|
59
|
+
read the token from header → cookie → query string via
|
|
60
|
+
`query_param=`, for cookieless `EventSource`/SSE clients), full
|
|
59
61
|
bundled flow (`UserAuthService` + `make_auth_router` covering
|
|
60
62
|
signup/activate/login/password-reset), `BaseUserModel` +
|
|
61
|
-
`BaseUserTokenModel
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
`
|
|
66
|
-
`
|
|
67
|
-
|
|
63
|
+
`BaseUserTokenModel` (nullable `payload` column carrying flow
|
|
64
|
+
context), email change/re-verify/recovery
|
|
65
|
+
(`request_email_change`/`confirm_email_change`,
|
|
66
|
+
`request_email_verification`/`confirm_email_verification`,
|
|
67
|
+
`request_email_recovery` — password + MFA-if-enrolled, opt-in
|
|
68
|
+
`AUTH_EMAIL_RECOVERY_ENABLED`; old-email security notice via
|
|
69
|
+
`AUTH_EMAIL_CHANGE_NOTIFY_OLD`; `EMAIL_CHANGE` token purpose;
|
|
70
|
+
JSON + backend HTML pages + bilingual templates), OAuth2/OIDC
|
|
71
|
+
providers (`GoogleOAuthClient`, `GitHubOAuthClient`,
|
|
72
|
+
`OIDCProvider`), CSRF middleware + `make_csrf_token_dependency`,
|
|
73
|
+
opt-in DB-backed opaque refresh tokens
|
|
74
|
+
(`BaseUserRefreshTokenModel`, `make_user_refresh_token_model`,
|
|
75
|
+
`refresh_token_model=` on `UserAuthService`) with rotation,
|
|
76
|
+
family-wide reuse detection and `POST /auth/logout`
|
|
77
|
+
(`LogoutSchema`).
|
|
68
78
|
- **DB** — `AsyncDatabaseManager`, `BaseRepository[T]` with
|
|
69
79
|
bulk ops (`bulk_create_values`, `bulk_upsert`, `bulk_update`,
|
|
70
80
|
`add_all`, etc.), `AlembicHelper`, `BaseModel`, audit /
|
|
@@ -88,9 +98,14 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
|
|
|
88
98
|
- **Pagination** — offset + cursor.
|
|
89
99
|
- **Settings mixins** — every `*Settings` carries
|
|
90
100
|
`title`/`description`/`examples` on every field.
|
|
91
|
-
- **SSE** — `EventStream
|
|
92
|
-
`
|
|
93
|
-
|
|
101
|
+
- **SSE** — `EventStream` (bounded queue + `overflow` backpressure —
|
|
102
|
+
`drop_oldest`/`drop_newest`/`block`, `dropped_events` counter,
|
|
103
|
+
`max_queue=0` to disable), `ServerSentEvent`, `sse_response`
|
|
104
|
+
(`on_disconnect=` cleanup), `EventStream.response`, and `SSEBroker`
|
|
105
|
+
(per-channel fan-out; `SSEBroker.response(channel)` bundles
|
|
106
|
+
register + response + unregister-on-disconnect; in-memory
|
|
107
|
+
single-process, or multi-worker via an injected Redis pub/sub bridge
|
|
108
|
+
— same call site).
|
|
94
109
|
- **Throttle** — `AttemptThrottle` (any `ThrottleBackend`, e.g.
|
|
95
110
|
`redis.asyncio.Redis`; no in-memory backend bundled).
|
|
96
111
|
- **Base CRUD layers** — `BaseService[Repo, Resp, UpdateT]` and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tempest-fastapi-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.92.0
|
|
4
4
|
Summary: Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects.
|
|
5
5
|
Project-URL: Homepage, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
|
|
6
6
|
Project-URL: Repository, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
|
|
@@ -200,7 +200,7 @@ Via `pyproject.toml`:
|
|
|
200
200
|
|
|
201
201
|
```toml
|
|
202
202
|
dependencies = [
|
|
203
|
-
"tempest-fastapi-sdk>=0.
|
|
203
|
+
"tempest-fastapi-sdk>=0.91.0",
|
|
204
204
|
]
|
|
205
205
|
```
|
|
206
206
|
|
|
@@ -253,12 +253,12 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
|
|
|
253
253
|
| `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException`, i18n (`MessageCatalog`, `default_message_catalog`, `parse_accept_language`, `DEFAULT_LOCALE`) |
|
|
254
254
|
| `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
|
|
255
255
|
| `tempest_fastapi_sdk.api` | `register_exception_handlers`, `app_exception_handler`, `apply_cors`, `make_health_router`, `make_logs_router`, `make_prometheus_router`, `make_prometheus_registry`, `PrometheusMiddleware`, `LogSource`, `make_tool_spec_router`, `make_token_dependency`, `make_bearer_token_dependency`, `make_jwt_user_dependency`, `make_role_dependency`, `make_permission_dependency`, `require_x_token`, `run_server`, `RequestIDMiddleware`, `RateLimitMiddleware` (+ `RateLimitStore`/`MemoryRateLimitStore`/`RedisRateLimitStore`/`RateLimitResult` and `key_by_ip`/`key_by_jwt_subject`/`key_by_jwt_claim`/`key_by_header`), `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `GracefulShutdownMiddleware`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
|
|
256
|
-
| `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + TOTP 2FA out of the box |
|
|
256
|
+
| `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, email change/verify/recovery (`EmailChangeRequestSchema` / `EmailChangeConfirmSchema` / `EmailRecoveryRequestSchema` / `EmailChangeToken` / `EmailVerificationToken`, old-email security notice, opt-in `AUTH_EMAIL_RECOVERY_ENABLED`), MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + email change/recovery + TOTP 2FA out of the box |
|
|
257
257
|
| `tempest_fastapi_sdk.controllers` | `BaseController` |
|
|
258
258
|
| `tempest_fastapi_sdk.services` | `BaseService` |
|
|
259
259
|
| `tempest_fastapi_sdk.core` | `configure_logging`, `JSONFormatter`, `get_request_id`/`set_request_id`/`clear_request_id`, `request_id_ctx`, `BaseStrEnum`, `BaseIntEnum`, `strict_types`/`typed`/`require_annotations` |
|
|
260
260
|
| `tempest_fastapi_sdk.admin` *(extra: `[admin]`)* | `AdminSite`, `AdminModel`, `make_admin_router`, `AdminAuthBackend`, `UserModelAuthBackend`, `AdminAuthError` |
|
|
261
|
-
| `tempest_fastapi_sdk.sse` | `EventStream
|
|
261
|
+
| `tempest_fastapi_sdk.sse` | `EventStream` (bounded queue + `overflow` backpressure), `SSEBroker` (multi-worker fan-out via Redis, `.response()` lifecycle helper), `ServerSentEvent`, `sse_response` (`on_disconnect=` cleanup) |
|
|
262
262
|
| `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
|
|
263
263
|
| `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
|
|
264
264
|
| `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `make_web_push_router`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
|
|
@@ -2445,7 +2445,7 @@ import asyncio
|
|
|
2445
2445
|
|
|
2446
2446
|
from fastapi import APIRouter
|
|
2447
2447
|
|
|
2448
|
-
from tempest_fastapi_sdk import EventStream
|
|
2448
|
+
from tempest_fastapi_sdk import EventStream
|
|
2449
2449
|
|
|
2450
2450
|
router = APIRouter()
|
|
2451
2451
|
|
|
@@ -2460,8 +2460,9 @@ async def events() -> "StreamingResponse": # forward-declared by Starlette
|
|
|
2460
2460
|
await asyncio.sleep(1)
|
|
2461
2461
|
await stream.close()
|
|
2462
2462
|
|
|
2463
|
-
asyncio.create_task(producer())
|
|
2464
|
-
|
|
2463
|
+
task = asyncio.create_task(producer())
|
|
2464
|
+
# on_disconnect cancels the producer when the client drops — no leak.
|
|
2465
|
+
return stream.response(on_disconnect=task.cancel)
|
|
2465
2466
|
```
|
|
2466
2467
|
|
|
2467
2468
|
Browser side:
|
|
@@ -2473,6 +2474,8 @@ es.addEventListener("counter", (e) => console.log("got", JSON.parse(e.data)));
|
|
|
2473
2474
|
|
|
2474
2475
|
`heartbeat_seconds` emits a `: keepalive` SSE comment when idle so load-balancers don't close long-lived connections. `ServerSentEvent.data` accepts strings, bytes or any JSON-serializable Python object — non-strings are JSON-encoded automatically. Pass `retry=` to hint the browser at the reconnect delay (milliseconds).
|
|
2475
2476
|
|
|
2477
|
+
The queue is **bounded** (`max_queue`, default `1000`): a slow client can't grow memory without limit. `overflow` picks the eviction policy — `"drop_oldest"` (default), `"drop_newest"`, or `"block"` (real backpressure); `EventStream.dropped_events` counts the discards. For broadcast, `SSEBroker.response(channel)` bundles `register` + `sse_response` + `unregister`-on-disconnect in one call. Authenticating an `EventSource` (which can't send an `Authorization` header): prefer a session cookie (`make_jwt_user_dependency(..., cookie_name="access_token")` + `withCredentials`); for cookieless clients pass a short-lived access token in the query string with `query_param="access_token"` (over TLS, scrubbed from logs). See the [SSE recipe](https://mauriciobenjamin700.github.io/tempest-fastapi-sdk/recipes/sse/) for the full guide.
|
|
2478
|
+
|
|
2476
2479
|
### Web Push notifications recipe
|
|
2477
2480
|
|
|
2478
2481
|
`WebPushDispatcher` wraps the synchronous `pywebpush` library in `asyncio.to_thread` and surfaces the two errors the application cares about: `WebPushGoneError` (HTTP 404/410 — delete the subscription) and `WebPushError` (everything else). Install with `[webpush]`.
|
|
@@ -91,7 +91,7 @@ Via `pyproject.toml`:
|
|
|
91
91
|
|
|
92
92
|
```toml
|
|
93
93
|
dependencies = [
|
|
94
|
-
"tempest-fastapi-sdk>=0.
|
|
94
|
+
"tempest-fastapi-sdk>=0.91.0",
|
|
95
95
|
]
|
|
96
96
|
```
|
|
97
97
|
|
|
@@ -144,12 +144,12 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
|
|
|
144
144
|
| `tempest_fastapi_sdk.exceptions` | `AppException`, `NotFoundException`, `ConflictException`, `ValidationException`, `UnauthorizedException`, `ForbiddenException`, `InvalidTokenException`, `ExpiredTokenException`, `FileTooLargeException`, `InvalidFileTypeException`, `TooManyRequestsException`, i18n (`MessageCatalog`, `default_message_catalog`, `parse_accept_language`, `DEFAULT_LOCALE`) |
|
|
145
145
|
| `tempest_fastapi_sdk.settings` | `BaseAppSettings`, `ServerSettings`, `LogSettings`, `DatabaseSettings`, `RedisSettings`, `RabbitMQSettings`, `JWTSettings`, `CORSSettings`, `EmailSettings`, `UploadSettings`, `TokenSettings`, `WebPushSettings`, `TaskIQSettings`, `MinIOSettings`, `AuthSettings` |
|
|
146
146
|
| `tempest_fastapi_sdk.api` | `register_exception_handlers`, `app_exception_handler`, `apply_cors`, `make_health_router`, `make_logs_router`, `make_prometheus_router`, `make_prometheus_registry`, `PrometheusMiddleware`, `LogSource`, `make_tool_spec_router`, `make_token_dependency`, `make_bearer_token_dependency`, `make_jwt_user_dependency`, `make_role_dependency`, `make_permission_dependency`, `require_x_token`, `run_server`, `RequestIDMiddleware`, `RateLimitMiddleware` (+ `RateLimitStore`/`MemoryRateLimitStore`/`RedisRateLimitStore`/`RateLimitResult` and `key_by_ip`/`key_by_jwt_subject`/`key_by_jwt_claim`/`key_by_header`), `IdempotencyMiddleware`, `MemoryIdempotencyStore`, `RedisIdempotencyStore`, `BodySizeLimitMiddleware`, `CSRFMiddleware`, `make_csrf_token_dependency`, `GracefulShutdownMiddleware`, `WebhookSignatureVerifier`, `RSAWebhookSignatureVerifier`, OAuth2 (`GoogleOAuthClient`, `GitHubOAuthClient`, `OIDCProvider`), `HardenedStaticFiles`, `DEFAULT_STATIC_SECURITY_HEADERS`, `set_cookie`, `clear_cookie`, `SameSite`, `HealthCheck`, `setup_tracing` *(extra: `[otel]`)* |
|
|
147
|
-
| `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + TOTP 2FA out of the box |
|
|
147
|
+
| `tempest_fastapi_sdk.auth` *(extra: `[auth]`, opcional `[email]`, `[mfa]`)* | `UserAuthService`, `make_auth_router`, `SignupSchema` / `LoginSchema` / `RefreshSchema` / `PasswordResetRequestSchema` / `PasswordResetConfirmSchema` + responses, `ActivationToken`, `PasswordResetToken`, email change/verify/recovery (`EmailChangeRequestSchema` / `EmailChangeConfirmSchema` / `EmailRecoveryRequestSchema` / `EmailChangeToken` / `EmailVerificationToken`, old-email security notice, opt-in `AUTH_EMAIL_RECOVERY_ENABLED`), MFA schemas (`MFAEnrollResponseSchema` / `MFAConfirmSchema` / `MFAVerifySchema` / `MFADisableSchema`), opt-in DB-backed refresh tokens (`BaseUserRefreshTokenModel` / `make_user_refresh_token_model` / `LogoutSchema`) with rotation + reuse detection + `POST /auth/logout`, bilingual emails + backend pages (`AUTH_DEFAULT_LOCALE`, `normalize_locale` / `negotiate_locale`) — signup/activate/login/refresh/logout/reset + email change/recovery + TOTP 2FA out of the box |
|
|
148
148
|
| `tempest_fastapi_sdk.controllers` | `BaseController` |
|
|
149
149
|
| `tempest_fastapi_sdk.services` | `BaseService` |
|
|
150
150
|
| `tempest_fastapi_sdk.core` | `configure_logging`, `JSONFormatter`, `get_request_id`/`set_request_id`/`clear_request_id`, `request_id_ctx`, `BaseStrEnum`, `BaseIntEnum`, `strict_types`/`typed`/`require_annotations` |
|
|
151
151
|
| `tempest_fastapi_sdk.admin` *(extra: `[admin]`)* | `AdminSite`, `AdminModel`, `make_admin_router`, `AdminAuthBackend`, `UserModelAuthBackend`, `AdminAuthError` |
|
|
152
|
-
| `tempest_fastapi_sdk.sse` | `EventStream
|
|
152
|
+
| `tempest_fastapi_sdk.sse` | `EventStream` (bounded queue + `overflow` backpressure), `SSEBroker` (multi-worker fan-out via Redis, `.response()` lifecycle helper), `ServerSentEvent`, `sse_response` (`on_disconnect=` cleanup) |
|
|
153
153
|
| `tempest_fastapi_sdk.cache` *(extra: `[cache]`)* | `AsyncRedisManager`, `cached` (with `namespace` / `tags`), `CacheInvalidator`, `namespace_registry_key`, `tag_registry_key` |
|
|
154
154
|
| `tempest_fastapi_sdk.flags` | `FeatureFlags`, `FeatureFlagBackend`, `MemoryFeatureFlagBackend`, `EnvFeatureFlagBackend`, `RedisFeatureFlagBackend`, `CompositeFeatureFlagBackend`, `make_flag_dependency`, `coerce_flag` |
|
|
155
155
|
| `tempest_fastapi_sdk.webpush` *(extra: `[webpush]`)* | `WebPushDispatcher`, `WebPushSubscriptionService`, `make_web_push_router`, `WebPushError`, `WebPushGoneError`, `WebPushSubscriptionSchema`, `WebPushKeysSchema`, `WebPushPayloadSchema` |
|
|
@@ -2336,7 +2336,7 @@ import asyncio
|
|
|
2336
2336
|
|
|
2337
2337
|
from fastapi import APIRouter
|
|
2338
2338
|
|
|
2339
|
-
from tempest_fastapi_sdk import EventStream
|
|
2339
|
+
from tempest_fastapi_sdk import EventStream
|
|
2340
2340
|
|
|
2341
2341
|
router = APIRouter()
|
|
2342
2342
|
|
|
@@ -2351,8 +2351,9 @@ async def events() -> "StreamingResponse": # forward-declared by Starlette
|
|
|
2351
2351
|
await asyncio.sleep(1)
|
|
2352
2352
|
await stream.close()
|
|
2353
2353
|
|
|
2354
|
-
asyncio.create_task(producer())
|
|
2355
|
-
|
|
2354
|
+
task = asyncio.create_task(producer())
|
|
2355
|
+
# on_disconnect cancels the producer when the client drops — no leak.
|
|
2356
|
+
return stream.response(on_disconnect=task.cancel)
|
|
2356
2357
|
```
|
|
2357
2358
|
|
|
2358
2359
|
Browser side:
|
|
@@ -2364,6 +2365,8 @@ es.addEventListener("counter", (e) => console.log("got", JSON.parse(e.data)));
|
|
|
2364
2365
|
|
|
2365
2366
|
`heartbeat_seconds` emits a `: keepalive` SSE comment when idle so load-balancers don't close long-lived connections. `ServerSentEvent.data` accepts strings, bytes or any JSON-serializable Python object — non-strings are JSON-encoded automatically. Pass `retry=` to hint the browser at the reconnect delay (milliseconds).
|
|
2366
2367
|
|
|
2368
|
+
The queue is **bounded** (`max_queue`, default `1000`): a slow client can't grow memory without limit. `overflow` picks the eviction policy — `"drop_oldest"` (default), `"drop_newest"`, or `"block"` (real backpressure); `EventStream.dropped_events` counts the discards. For broadcast, `SSEBroker.response(channel)` bundles `register` + `sse_response` + `unregister`-on-disconnect in one call. Authenticating an `EventSource` (which can't send an `Authorization` header): prefer a session cookie (`make_jwt_user_dependency(..., cookie_name="access_token")` + `withCredentials`); for cookieless clients pass a short-lived access token in the query string with `query_param="access_token"` (over TLS, scrubbed from logs). See the [SSE recipe](https://mauriciobenjamin700.github.io/tempest-fastapi-sdk/recipes/sse/) for the full guide.
|
|
2369
|
+
|
|
2367
2370
|
### Web Push notifications recipe
|
|
2368
2371
|
|
|
2369
2372
|
`WebPushDispatcher` wraps the synchronous `pywebpush` library in `asyncio.to_thread` and surfaces the two errors the application cares about: `WebPushGoneError` (HTTP 404/410 — delete the subscription) and `WebPushError` (everything else). Install with `[webpush]`.
|
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
Breaking-change walkthroughs grouped by minor release. Stick to the version that matches what you're upgrading **from**. The release sections are listed newest-first, so on a multi-version jump read and apply them bottom-up.
|
|
4
4
|
|
|
5
|
+
## 0.92.0 — `payload` column on the user token
|
|
6
|
+
|
|
7
|
+
0.92.0 adds the **email change / re-verification / recovery** flow. To carry the pending email until confirmation, `BaseUserTokenModel` gained a new column:
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
payload: Mapped[str | None] = mapped_column(String(320), nullable=True, default=None)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Since your `user_tokens` table inherits from `BaseUserTokenModel`, the column shows up on the model automatically — but the database needs a **migration**. It is additive and safe (nullable column, no required default):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# generate and apply
|
|
17
|
+
tempest db revision -m "add payload to user_tokens"
|
|
18
|
+
tempest db upgrade
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or by hand:
|
|
22
|
+
|
|
23
|
+
```sql
|
|
24
|
+
ALTER TABLE user_tokens ADD COLUMN payload VARCHAR(320) NULL;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
!!! info "That's it"
|
|
28
|
+
No renames, no default backfill. Existing flows (activation, password reset) keep writing `payload = NULL`. The new email flow is fully opt-in — recovery (`POST /auth/email-recovery/request`) is only mounted with `AUTH_EMAIL_RECOVERY_ENABLED=True`.
|
|
29
|
+
|
|
30
|
+
### Verify
|
|
31
|
+
|
|
32
|
+
- Run the migration before deploying 0.92.0 (the column must exist).
|
|
33
|
+
- If you hand-write `src/db/models/user_token.py` instead of using `make_user_token_model`, the column comes from the abstract base — no need to redeclare, just migrate.
|
|
34
|
+
|
|
5
35
|
## 0.63.0 — authenticated user loaded on the request session
|
|
6
36
|
|
|
7
37
|
Before 0.63.0, `UserAuthService.current_user_dependency()` loaded the authenticated user through `load_user`, which opened its **own** session (via `db.get_session_context()`) and closed it on exit. The `UserModel` handed to the route was therefore **detached**: mutating it and calling `commit`/`refresh` on the request session (the one your repositories use) raised
|
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
Passo a passo das mudanças que quebram compatibilidade, agrupadas por release minor. Siga a versão que casa com aquela **de onde** você está atualizando. As seções estão listadas da mais nova para a mais antiga, então num salto de várias versões leia e aplique-as de baixo para cima.
|
|
4
4
|
|
|
5
|
+
## 0.92.0 — coluna `payload` no token de usuário
|
|
6
|
+
|
|
7
|
+
A 0.92.0 adiciona o fluxo de **troca / re-verificação / recuperação de e-mail**. Para carregar o e-mail pendente até a confirmação, `BaseUserTokenModel` ganhou uma coluna nova:
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
payload: Mapped[str | None] = mapped_column(String(320), nullable=True, default=None)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Como sua tabela `user_tokens` herda de `BaseUserTokenModel`, a coluna aparece automaticamente no modelo — mas o banco precisa de uma **migration**. É aditiva e segura (coluna anulável, sem default obrigatório):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# gere e aplique
|
|
17
|
+
tempest db revision -m "add payload to user_tokens"
|
|
18
|
+
tempest db upgrade
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Ou, na mão:
|
|
22
|
+
|
|
23
|
+
```sql
|
|
24
|
+
ALTER TABLE user_tokens ADD COLUMN payload VARCHAR(320) NULL;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
!!! info "Só isso"
|
|
28
|
+
Nenhuma renomeação, nenhum default backfill. Fluxos existentes (ativação, reset de senha) continuam gravando `payload = NULL`. O novo fluxo de e-mail é totalmente opt-in — a recuperação (`POST /auth/email-recovery/request`) só é montada com `AUTH_EMAIL_RECOVERY_ENABLED=True`.
|
|
29
|
+
|
|
30
|
+
### Verifique
|
|
31
|
+
|
|
32
|
+
- Rode a migration antes de subir a 0.92.0 (a coluna precisa existir).
|
|
33
|
+
- Se você escreve `src/db/models/user_token.py` à mão em vez de usar `make_user_token_model`, a coluna vem da base abstrata — não precisa redeclarar, só migrar.
|
|
34
|
+
|
|
5
35
|
## 0.63.0 — usuário autenticado carregado na sessão de request
|
|
6
36
|
|
|
7
37
|
Antes da 0.63.0, `UserAuthService.current_user_dependency()` carregava o usuário autenticado chamando `load_user`, que abria a **própria** sessão (via `db.get_session_context()`) e a fechava ao terminar. O `UserModel` entregue à rota ficava **detached**: mutá-lo e dar `commit`/`refresh` na sessão de request (a dos seus repositories) levantava
|
|
@@ -130,6 +130,11 @@ uv run tempest db upgrade
|
|
|
130
130
|
| POST | `/auth/password-reset/request` | `PasswordResetRequestSchema` → `PasswordResetResponseSchema` | Always HTTP 202 + generic body. Link via email (A/B) or body (C). |
|
|
131
131
|
| POST | `/auth/password-reset/confirm` | `PasswordResetConfirmSchema` → `LoginResponseSchema` | Consumes token + writes new password + issues JWT pair. |
|
|
132
132
|
| POST | `/auth/password-change` | `PasswordChangeSchema` → `204` | **Authenticated** (bearer token). Change your own password: confirm the current password + write the new one. No email token. |
|
|
133
|
+
| POST | `/auth/email-change/request` *(v0.92.0+)* | `EmailChangeRequestSchema` → `EmailChangeResponseSchema` | **Authenticated.** Confirm the current password + email a confirmation link to the **new** address. Always 202. |
|
|
134
|
+
| POST | `/auth/email-change/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consume the token + apply the new email + (optionally) notify the old address. |
|
|
135
|
+
| POST | `/auth/email-verify/request` *(v0.92.0+)* | — → `EmailChangeResponseSchema` | **Authenticated.** Re-send a verification link to the **current** email. |
|
|
136
|
+
| POST | `/auth/email-verify/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consume the token + mark the account active. |
|
|
137
|
+
| POST | `/auth/email-recovery/request` *(v0.92.0+, opt-in)* | `EmailRecoveryRequestSchema` → `EmailChangeResponseSchema` | **Unauthenticated.** Recover an account whose mailbox is lost: password (+ MFA if enrolled). Only mounted with `AUTH_EMAIL_RECOVERY_ENABLED=True`. Always 202. |
|
|
133
138
|
| POST | `/auth/refresh` *(v0.65.0+)* | `RefreshSchema` → `LoginResponseSchema` | Exchange a valid **refresh token** for a fresh JWT pair. **No email/password.** Rejects a replayed access token (401) and inactive accounts (403). |
|
|
134
139
|
|
|
135
140
|
!!! tip "`password-reset/confirm` vs `password-change` — which is which?"
|
|
@@ -145,6 +150,50 @@ uv run tempest db upgrade
|
|
|
145
150
|
`current_password`. No email or reset token involved. Returns
|
|
146
151
|
**204** and the current tokens stay valid.
|
|
147
152
|
|
|
153
|
+
## Email change, verification and recovery (v0.92.0+)
|
|
154
|
+
|
|
155
|
+
Mirrors the password flow, but for the account **email**. Three cases:
|
|
156
|
+
|
|
157
|
+
- **Change email (logged in)** — like `password-change`: the user is
|
|
158
|
+
logged in, confirms `current_password` and supplies `new_email`. A
|
|
159
|
+
confirmation link goes to the **new** address; the email only changes
|
|
160
|
+
once that link is confirmed. On confirmation a security notice is sent
|
|
161
|
+
to the **old** address (the banks/Google pattern).
|
|
162
|
+
- **Re-verify the current email** — re-send a verification link to the
|
|
163
|
+
current address (useful when the activation email was lost).
|
|
164
|
+
- **Recovery (lost mailbox access)** — an **unauthenticated** endpoint,
|
|
165
|
+
opt-in via `AUTH_EMAIL_RECOVERY_ENABLED`. Proves identity with the
|
|
166
|
+
password **and a valid MFA code when TOTP is enrolled**, then emails the
|
|
167
|
+
link to the new address.
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
# Change email (logged in) — token comes in the body in dev (mode C)
|
|
171
|
+
resp = await client.post(
|
|
172
|
+
"/auth/email-change/request",
|
|
173
|
+
json={"new_email": "new@example.com", "current_password": "current-pass"},
|
|
174
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
|
175
|
+
)
|
|
176
|
+
confirm_url: str | None = resp.json()["confirm_url"] # None in prod (goes by email)
|
|
177
|
+
|
|
178
|
+
# ...user opens the link; the front extracts the token and confirms:
|
|
179
|
+
await client.post("/auth/email-change/confirm", json={"token": token})
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
!!! danger "Recovery is sensitive — enable it deliberately"
|
|
183
|
+
`POST /auth/email-recovery/request` lets whoever has the password move
|
|
184
|
+
the account to another email **without** accessing the old mailbox. It
|
|
185
|
+
is only mounted with `AUTH_EMAIL_RECOVERY_ENABLED=True`. It always
|
|
186
|
+
answers a generic **202** (no account enumeration) and, when TOTP is
|
|
187
|
+
enrolled, requires a valid `mfa_code`. Keep
|
|
188
|
+
`AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` so the old address is always
|
|
189
|
+
alerted.
|
|
190
|
+
|
|
191
|
+
!!! info "Where the new email is stored"
|
|
192
|
+
The pending address travels in the token's `payload` column
|
|
193
|
+
(`EMAIL_CHANGE`), not on the `UserModel`. Confirmation re-reads the
|
|
194
|
+
`payload`, re-checks the address is still free (a request→confirm race
|
|
195
|
+
→ **409**) and only then writes it. See the 0.92.0 migration note.
|
|
196
|
+
|
|
148
197
|
### Renewing the session with the refresh token
|
|
149
198
|
|
|
150
199
|
The `access_token` is short-lived by design (`JWT_ACCESS_TTL_SECONDS`,
|
|
@@ -130,6 +130,11 @@ uv run tempest db upgrade
|
|
|
130
130
|
| POST | `/auth/password-reset/request` | `PasswordResetRequestSchema` → `PasswordResetResponseSchema` | Sempre HTTP 202 + corpo genérico. Link via e-mail (A/B) ou no body (C). |
|
|
131
131
|
| POST | `/auth/password-reset/confirm` | `PasswordResetConfirmSchema` → `LoginResponseSchema` | Consome token + grava nova senha + emite JWT pair. |
|
|
132
132
|
| POST | `/auth/password-change` | `PasswordChangeSchema` → `204` | **Autenticado** (bearer token). Troca a própria senha: confirma a senha atual + grava a nova. Sem token de e-mail. |
|
|
133
|
+
| POST | `/auth/email-change/request` *(v0.92.0+)* | `EmailChangeRequestSchema` → `EmailChangeResponseSchema` | **Autenticado.** Confirma a senha atual + envia link de confirmação pro **novo** e-mail. Sempre 202. |
|
|
134
|
+
| POST | `/auth/email-change/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consome o token + aplica o novo e-mail + (opcional) avisa o e-mail antigo. |
|
|
135
|
+
| POST | `/auth/email-verify/request` *(v0.92.0+)* | — → `EmailChangeResponseSchema` | **Autenticado.** Reenvia link de verificação pro e-mail **atual**. |
|
|
136
|
+
| POST | `/auth/email-verify/confirm` *(v0.92.0+)* | `EmailChangeConfirmSchema` → `EmailChangeResponseSchema` | Consome o token + marca a conta ativa. |
|
|
137
|
+
| POST | `/auth/email-recovery/request` *(v0.92.0+, opt-in)* | `EmailRecoveryRequestSchema` → `EmailChangeResponseSchema` | **Não autenticado.** Recupera conta cujo e-mail se perdeu: senha (+ MFA se inscrito). Só montado com `AUTH_EMAIL_RECOVERY_ENABLED=True`. Sempre 202. |
|
|
133
138
|
| POST | `/auth/refresh` *(v0.65.0+)* | `RefreshSchema` → `LoginResponseSchema` | Troca um **refresh token** válido por um JWT pair novo. **Sem email/senha.** Rejeita access token replayado (401) e conta inativa (403). |
|
|
134
139
|
|
|
135
140
|
!!! tip "`password-reset/confirm` vs `password-change` — qual é qual?"
|
|
@@ -144,6 +149,50 @@ uv run tempest db upgrade
|
|
|
144
149
|
nem token de reset. Retorna **204** e os tokens atuais continuam
|
|
145
150
|
válidos.
|
|
146
151
|
|
|
152
|
+
## Troca, verificação e recuperação de e-mail (v0.92.0+)
|
|
153
|
+
|
|
154
|
+
Espelha o fluxo de senha, mas pro **e-mail** da conta. Três cenários:
|
|
155
|
+
|
|
156
|
+
- **Trocar e-mail (logado)** — como `password-change`: o usuário está
|
|
157
|
+
logado, confirma a `current_password` e informa o `new_email`. Um link
|
|
158
|
+
de confirmação vai pro **novo** endereço; o e-mail só muda quando esse
|
|
159
|
+
link é confirmado. Ao confirmar, um aviso de segurança vai pro endereço
|
|
160
|
+
**antigo** (padrão de bancos/Google).
|
|
161
|
+
- **Re-verificar o e-mail atual** — reenvia um link de verificação pro
|
|
162
|
+
endereço atual (útil quando o e-mail de ativação se perdeu).
|
|
163
|
+
- **Recuperação (perdeu acesso ao e-mail)** — endpoint **não
|
|
164
|
+
autenticado**, opt-in via `AUTH_EMAIL_RECOVERY_ENABLED`. Prova
|
|
165
|
+
identidade com a senha **e um código MFA quando o TOTP está inscrito**,
|
|
166
|
+
e manda o link pro novo endereço.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
# Trocar e-mail (logado) — pega o token no body em dev (modo C)
|
|
170
|
+
resp = await client.post(
|
|
171
|
+
"/auth/email-change/request",
|
|
172
|
+
json={"new_email": "nova@example.com", "current_password": "senha-atual"},
|
|
173
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
|
174
|
+
)
|
|
175
|
+
confirm_url: str | None = resp.json()["confirm_url"] # None em produção (vai por e-mail)
|
|
176
|
+
|
|
177
|
+
# ...usuário abre o link; o front extrai o token e confirma:
|
|
178
|
+
await client.post("/auth/email-change/confirm", json={"token": token})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
!!! danger "Recuperação é sensível — ligue com cuidado"
|
|
182
|
+
`POST /auth/email-recovery/request` deixa quem tem a senha mover a
|
|
183
|
+
conta pra outro e-mail **sem** acessar a caixa antiga. Só é montado
|
|
184
|
+
com `AUTH_EMAIL_RECOVERY_ENABLED=True`. Sempre responde **202**
|
|
185
|
+
genérico (não enumera contas) e, se o TOTP estiver inscrito, exige um
|
|
186
|
+
`mfa_code` válido. Mantenha `AUTH_EMAIL_CHANGE_NOTIFY_OLD=True` pra o
|
|
187
|
+
endereço antigo sempre ser avisado.
|
|
188
|
+
|
|
189
|
+
!!! info "Onde o novo e-mail fica guardado"
|
|
190
|
+
O endereço pendente viaja na coluna `payload` do token
|
|
191
|
+
(`EMAIL_CHANGE`), não no `UserModel`. A confirmação relê o `payload`,
|
|
192
|
+
re-checa que o endereço ainda está livre (corrida entre pedido e
|
|
193
|
+
confirmação → **409**) e só então grava. Veja a nota de migração da
|
|
194
|
+
0.92.0.
|
|
195
|
+
|
|
147
196
|
### Renovando a sessão com o refresh token
|
|
148
197
|
|
|
149
198
|
O `access_token` é curto por design (`JWT_ACCESS_TTL_SECONDS`, 1 h por
|