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