svc-infra 0.1.594__tar.gz → 0.1.595__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.
Potentially problematic release.
This version of svc-infra might be problematic. Click here for more details.
- {svc_infra-0.1.594 → svc_infra-0.1.595}/PKG-INFO +1 -1
- {svc_infra-0.1.594 → svc_infra-0.1.595}/pyproject.toml +1 -1
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/README.md +26 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/apf_payments/router.py +67 -6
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/oauth_router.py +7 -2
- svc_infra-0.1.595/src/svc_infra/api/fastapi/middleware/ratelimit_store.py +78 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/session.py +11 -2
- svc_infra-0.1.594/src/svc_infra/api/fastapi/middleware/ratelimit_store.py +0 -30
- {svc_infra-0.1.594 → svc_infra-0.1.595}/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/alembic.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/models.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/provider/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/provider/aiydan.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/provider/base.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/provider/registry.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/provider/stripe.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/schemas.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/service.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/apf_payments/settings.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/apf_payments/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/apf_payments/setup.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/_cookies.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/add.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/gaurd.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/mfa/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/mfa/models.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/mfa/pre_auth.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/mfa/router.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/mfa/security.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/mfa/utils.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/mfa/verify.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/policy.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/providers.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/account.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/apikey_router.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/session_router.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/security.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/sender.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/settings.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/state.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/cache/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/cache/add.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/http.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/nosql/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/nosql/mongo/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/nosql/mongo/add.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/nosql/mongo/crud_router.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/nosql/mongo/health.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/sql/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/sql/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/sql/add.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/sql/crud_router.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/sql/health.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/sql/session.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/sql/users.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dependencies/ratelimit.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/docs/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/docs/landing.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/docs/scoped.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dual/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dual/dualize.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dual/protected.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dual/public.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dual/router.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dual/utils.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/dx.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/ease.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/http/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/http/concurrency.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/http/conditional.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/http/deprecation.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/debug.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/catchall.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/exceptions.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/handlers.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/idempotency.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/ratelimit.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/request_id.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/request_size_limit.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/apply.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/conventions.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/models.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/mutators.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/pipeline.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/responses.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/openapi/security.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/pagination.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/paths/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/paths/auth.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/paths/generic.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/paths/prefix.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/paths/user.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/routers/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/routers/ping.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/setup.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/env.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/logging/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/logging/add.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/logging/filter.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/logging/formats.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/app/root.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/backend.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/decorators.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/demo.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/keys.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/recache.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/resources.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/tags.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/ttl.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cache/utils.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/nosql/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/nosql/mongo/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/nosql/mongo/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/nosql/mongo/mongo_cmds.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/nosql/mongo/mongo_scaffold_cmds.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/sql/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/sql/alembic_cmds.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/db/sql/sql_scaffold_cmds.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/help.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/obs/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/cmds/obs/obs_cmds.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/foundation/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/foundation/runner.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/cli/foundation/typer_bootstrap.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/crud_schema.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/base.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/constants.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/core.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/indexes.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/management.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/client.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/settings.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/templates/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/templates/documents.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/templates/resources.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/mongo/templates/schemas.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/repository.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/resource.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/scaffold.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/service.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/service_with_hooks.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/types.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/nosql/utils.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/apikey.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/authref.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/base.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/constants.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/core.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/management.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/repository.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/resource.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/scaffold.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/service.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/service_with_hooks.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/models_schemas/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/models_schemas/auth/models.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/models_schemas/auth/schemas.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/models_schemas/entity/models.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/models_schemas/entity/schemas.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/setup/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/setup/alembic.ini.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/setup/env_async.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/setup/env_sync.py.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/templates/setup/script.py.mako.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/types.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/uniq.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/uniq_hooks.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/sql/utils.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/db/utils.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/mcp/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/mcp/svc_infra_mcp.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/add.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/cloud_dash.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/metrics/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/metrics/asgi.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/metrics/base.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/metrics/http.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/metrics/sqlalchemy.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/metrics.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/compose_cloud/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/compose_cloud/templates/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/compose_cloud/templates/agent.yaml.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/compose_cloud/templates/docker-compose.cloud.yml.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/dashboards/00_overview.json +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/dashboards/10_http.json +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/dashboards/20_db.json +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/dashboards/30_runtime.json +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/dashboards/40_clients.json +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/dashboards/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/templates/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/templates/docker-compose.yml.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/templates/prometheus.yml.tmpl +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/templates/provisioning/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/templates/provisioning/dashboards.yml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/providers/grafana/templates/provisioning/datasource.yml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/settings.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/grafana_dashboard.json +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/prometheus_rules.yml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/compose/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/compose/agent.yaml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/compose/docker-compose.yml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/fly/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/fly/agent.yaml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/fly/fly.toml.fragment +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/k8s/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/k8s/configmap.yaml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/k8s/deployment.yaml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/railway/Dockerfile +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/railway/README.md +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/railway/__init__.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/obs/templates/sidecars/railway/agent.yaml +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/py.typed +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/audit.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/audit_service.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/headers.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/hibp.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/jwt_rotation.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/lockout.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/models.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/org_invites.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/passwords.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/permissions.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/security/signed_cookies.py +0 -0
- {svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/utils.py +0 -0
|
@@ -111,6 +111,32 @@ app = setup_service_api(
|
|
|
111
111
|
add_payments(app, prefix="/payments")
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
**Tenant Context**
|
|
115
|
+
|
|
116
|
+
All payments endpoints require a tenant identifier. The FastAPI router now
|
|
117
|
+
derives it automatically from the authenticated principal:
|
|
118
|
+
|
|
119
|
+
- API key principals → ``principal.api_key.tenant_id``
|
|
120
|
+
- User principals → ``principal.user.tenant_id``
|
|
121
|
+
- Fallbacks: ``X-Tenant-Id`` request header or ``request.state.tenant_id``
|
|
122
|
+
|
|
123
|
+
If you need custom mapping logic (for example, translating API keys to an
|
|
124
|
+
external tenant registry), register an override during startup:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from svc_infra.api.fastapi.apf_payments.router import set_payments_tenant_resolver
|
|
128
|
+
|
|
129
|
+
async def resolve_tenant(request, identity, header):
|
|
130
|
+
# return a string tenant id, or None to fall back to the defaults
|
|
131
|
+
return "tenant-from-custom-logic"
|
|
132
|
+
|
|
133
|
+
set_payments_tenant_resolver(resolve_tenant)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If no tenant can be derived (and the override also returns ``None``), the
|
|
137
|
+
router responds with ``400 tenant_context_missing`` so callers can supply the
|
|
138
|
+
missing context explicitly.
|
|
139
|
+
|
|
114
140
|
**Environment-Based Configuration**
|
|
115
141
|
|
|
116
142
|
The `easy_service_app` reads these env vars automatically:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import inspect
|
|
4
|
+
from typing import Annotated, Awaitable, Callable, Literal, Optional, cast
|
|
4
5
|
|
|
5
|
-
from fastapi import Body, Depends, Header, Request, Response, status
|
|
6
|
+
from fastapi import Body, Depends, Header, HTTPException, Request, Response, status
|
|
6
7
|
from starlette.responses import JSONResponse
|
|
7
8
|
|
|
8
9
|
from svc_infra.apf_payments.schemas import (
|
|
@@ -47,6 +48,7 @@ from svc_infra.apf_payments.schemas import (
|
|
|
47
48
|
WebhookReplayOut,
|
|
48
49
|
)
|
|
49
50
|
from svc_infra.apf_payments.service import PaymentsService
|
|
51
|
+
from svc_infra.api.fastapi.auth.security import OptionalIdentity, Principal
|
|
50
52
|
from svc_infra.api.fastapi.db.sql.session import SqlSessionDep
|
|
51
53
|
from svc_infra.api.fastapi.dual import protected_router, public_router, service_router, user_router
|
|
52
54
|
from svc_infra.api.fastapi.dual.router import DualAPIRouter
|
|
@@ -69,10 +71,69 @@ def _tx_kind(kind: str) -> Literal["payment", "refund", "fee", "payout", "captur
|
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
# --- deps ---
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
TenantOverrideHook = Callable[
|
|
75
|
+
[Request, Optional[Principal], Optional[str]],
|
|
76
|
+
Awaitable[Optional[str]] | Optional[str],
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
_tenant_override_hook: TenantOverrideHook | None = None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def set_payments_tenant_resolver(resolver: TenantOverrideHook | None) -> None:
|
|
83
|
+
"""Override the default tenant resolution used by the payments router.
|
|
84
|
+
|
|
85
|
+
Projects can call this during startup to plug custom logic (e.g. multi-tenant
|
|
86
|
+
mappings). Passing ``None`` resets to the built-in behavior.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
global _tenant_override_hook
|
|
90
|
+
_tenant_override_hook = resolver
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def resolve_payments_tenant_id(
|
|
94
|
+
request: Request,
|
|
95
|
+
identity: OptionalIdentity = None,
|
|
96
|
+
tenant_header: Annotated[Optional[str], Header(alias="X-Tenant-Id", default=None)] = None,
|
|
97
|
+
) -> str:
|
|
98
|
+
"""Determine the tenant id for the current request.
|
|
99
|
+
|
|
100
|
+
The default strategy prefers authenticated principals (API keys first, then
|
|
101
|
+
user accounts) and falls back to the ``X-Tenant-Id`` header or ``request.state``.
|
|
102
|
+
Applications may override the behavior via
|
|
103
|
+
:func:`set_payments_tenant_resolver`.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
if _tenant_override_hook is not None:
|
|
107
|
+
maybe = _tenant_override_hook(request, identity, tenant_header)
|
|
108
|
+
if inspect.isawaitable(maybe): # pragma: no cover - depends on override type
|
|
109
|
+
maybe = await maybe
|
|
110
|
+
if maybe is not None:
|
|
111
|
+
return maybe
|
|
112
|
+
|
|
113
|
+
if identity:
|
|
114
|
+
api_key_tenant = getattr(getattr(identity, "api_key", None), "tenant_id", None)
|
|
115
|
+
if api_key_tenant:
|
|
116
|
+
return api_key_tenant
|
|
117
|
+
|
|
118
|
+
user_tenant = getattr(getattr(identity, "user", None), "tenant_id", None)
|
|
119
|
+
if user_tenant:
|
|
120
|
+
return user_tenant
|
|
121
|
+
|
|
122
|
+
if tenant_header:
|
|
123
|
+
return tenant_header
|
|
124
|
+
|
|
125
|
+
state_tenant = getattr(request.state, "tenant_id", None)
|
|
126
|
+
if state_tenant:
|
|
127
|
+
return state_tenant
|
|
128
|
+
|
|
129
|
+
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="tenant_context_missing")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
PaymentsTenantDep = Annotated[str, Depends(resolve_payments_tenant_id)]
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
async def get_service(session: SqlSessionDep, tenant_id: PaymentsTenantDep) -> PaymentsService:
|
|
136
|
+
return PaymentsService(session=session, tenant_id=tenant_id)
|
|
76
137
|
|
|
77
138
|
|
|
78
139
|
# --- routers grouped by auth posture (same prefix is fine; FastAPI merges) ---
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/oauth_router.py
RENAMED
|
@@ -738,12 +738,15 @@ def _create_oauth_router(
|
|
|
738
738
|
raise HTTPException(401, "invalid_refresh_token")
|
|
739
739
|
|
|
740
740
|
# Rotate refresh token
|
|
741
|
-
|
|
741
|
+
try:
|
|
742
|
+
new_raw, _new_rt = await rotate_session_refresh(session, current=found)
|
|
743
|
+
except ValueError:
|
|
744
|
+
# Token expired between validation and rotation; treat as invalid
|
|
745
|
+
raise HTTPException(401, "invalid_refresh_token") from None
|
|
742
746
|
|
|
743
747
|
# Write response (204) with new cookies
|
|
744
748
|
resp = Response(status_code=status.HTTP_204_NO_CONTENT)
|
|
745
749
|
await _set_cookie_on_response(resp, auth_backend, user, refresh_raw=new_raw)
|
|
746
|
-
return resp
|
|
747
750
|
|
|
748
751
|
# Dead code removed: MFA branch handled earlier in login flow, refresh returns 204 above.
|
|
749
752
|
if hasattr(policy, "on_token_refresh"):
|
|
@@ -752,5 +755,7 @@ def _create_oauth_router(
|
|
|
752
755
|
except Exception:
|
|
753
756
|
pass
|
|
754
757
|
|
|
758
|
+
return resp
|
|
759
|
+
|
|
755
760
|
# Return router at end of factory
|
|
756
761
|
return router
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from typing import Optional, Protocol, Tuple
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class RateLimitStore(Protocol):
|
|
8
|
+
def incr(self, key: str, window: int) -> Tuple[int, int, int]:
|
|
9
|
+
"""Increment and return (count, limit, resetEpoch).
|
|
10
|
+
|
|
11
|
+
Implementations should manage per-window buckets. The 'limit' is stored configuration.
|
|
12
|
+
"""
|
|
13
|
+
...
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class InMemoryRateLimitStore:
|
|
17
|
+
def __init__(self, limit: int = 120):
|
|
18
|
+
self.limit = limit
|
|
19
|
+
self._buckets: dict[tuple[str, int], int] = {}
|
|
20
|
+
|
|
21
|
+
def incr(self, key: str, window: int) -> Tuple[int, int, int]:
|
|
22
|
+
now = int(time.time())
|
|
23
|
+
win = now - (now % window)
|
|
24
|
+
count = self._buckets.get((key, win), 0) + 1
|
|
25
|
+
self._buckets[(key, win)] = count
|
|
26
|
+
reset = win + window
|
|
27
|
+
return count, self.limit, reset
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RedisRateLimitStore:
|
|
31
|
+
"""Fixed-window counter store using Redis.
|
|
32
|
+
|
|
33
|
+
Keys are of the form: {prefix}:{key}:{windowStart}
|
|
34
|
+
Values are incremented and expire automatically at window end.
|
|
35
|
+
|
|
36
|
+
This implementation uses atomic INCR and EXPIRE semantics. To avoid race conditions
|
|
37
|
+
on first-set expiry, we set expiry when the counter is created.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
redis_client,
|
|
43
|
+
*,
|
|
44
|
+
limit: int = 120,
|
|
45
|
+
prefix: str = "ratelimit",
|
|
46
|
+
clock: Optional[callable] = None,
|
|
47
|
+
):
|
|
48
|
+
self.redis = redis_client
|
|
49
|
+
self.limit = limit
|
|
50
|
+
self.prefix = prefix
|
|
51
|
+
self._clock = clock or time.time
|
|
52
|
+
|
|
53
|
+
def _window_key(self, key: str, window: int) -> tuple[str, int, str]:
|
|
54
|
+
now = int(self._clock())
|
|
55
|
+
win = now - (now % window)
|
|
56
|
+
redis_key = f"{self.prefix}:{key}:{win}"
|
|
57
|
+
return redis_key, win, now
|
|
58
|
+
|
|
59
|
+
def incr(self, key: str, window: int) -> Tuple[int, int, int]:
|
|
60
|
+
rkey, win, now = self._window_key(key, window)
|
|
61
|
+
# Increment; if this is the first time we've seen this window key, set expiry to window end
|
|
62
|
+
pipe = self.redis.pipeline()
|
|
63
|
+
pipe.incr(rkey)
|
|
64
|
+
pipe.ttl(rkey)
|
|
65
|
+
count, ttl = pipe.execute()
|
|
66
|
+
if ttl == -1: # key exists without expire or just created; set expire to end of window
|
|
67
|
+
expire_sec = (win + window) - now
|
|
68
|
+
if expire_sec <= 0:
|
|
69
|
+
expire_sec = window
|
|
70
|
+
try:
|
|
71
|
+
self.redis.expire(rkey, expire_sec)
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
74
|
+
reset = win + window
|
|
75
|
+
return int(count), self.limit, reset
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
__all__ = ["RateLimitStore", "InMemoryRateLimitStore", "RedisRateLimitStore"]
|
|
@@ -64,15 +64,24 @@ async def rotate_session_refresh(
|
|
|
64
64
|
|
|
65
65
|
Returns: (new_raw_refresh_token, new_refresh_token_model)
|
|
66
66
|
"""
|
|
67
|
+
rotation_ts = datetime.now(timezone.utc)
|
|
68
|
+
if current.revoked_at:
|
|
69
|
+
raise ValueError("refresh token already revoked")
|
|
70
|
+
if current.expires_at and current.expires_at <= rotation_ts:
|
|
71
|
+
raise ValueError("refresh token expired")
|
|
67
72
|
new_raw, new_hash, expires_at = rotate_refresh_token(
|
|
68
73
|
current.token_hash, ttl_minutes=ttl_minutes
|
|
69
74
|
)
|
|
70
|
-
current.rotated_at =
|
|
75
|
+
current.rotated_at = rotation_ts
|
|
76
|
+
current.revoked_at = rotation_ts
|
|
77
|
+
current.revoke_reason = "rotated"
|
|
78
|
+
if current.expires_at is None or current.expires_at > rotation_ts:
|
|
79
|
+
current.expires_at = rotation_ts
|
|
71
80
|
# create revocation entry for old hash
|
|
72
81
|
db.add(
|
|
73
82
|
RefreshTokenRevocation(
|
|
74
83
|
token_hash=current.token_hash,
|
|
75
|
-
revoked_at=
|
|
84
|
+
revoked_at=rotation_ts,
|
|
76
85
|
reason="rotated",
|
|
77
86
|
)
|
|
78
87
|
)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import time
|
|
4
|
-
from typing import Protocol, Tuple
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class RateLimitStore(Protocol):
|
|
8
|
-
def incr(self, key: str, window: int) -> Tuple[int, int, int]:
|
|
9
|
-
"""Increment and return (count, limit, resetEpoch).
|
|
10
|
-
|
|
11
|
-
Implementations should manage per-window buckets. The 'limit' is stored configuration.
|
|
12
|
-
"""
|
|
13
|
-
...
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class InMemoryRateLimitStore:
|
|
17
|
-
def __init__(self, limit: int = 120):
|
|
18
|
-
self.limit = limit
|
|
19
|
-
self._buckets: dict[tuple[str, int], int] = {}
|
|
20
|
-
|
|
21
|
-
def incr(self, key: str, window: int) -> Tuple[int, int, int]:
|
|
22
|
-
now = int(time.time())
|
|
23
|
-
win = now - (now % window)
|
|
24
|
-
count = self._buckets.get((key, win), 0) + 1
|
|
25
|
-
self._buckets[(key, win)] = count
|
|
26
|
-
reset = win + window
|
|
27
|
-
return count, self.limit, reset
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
__all__ = ["RateLimitStore", "InMemoryRateLimitStore"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/apikey_router.py
RENAMED
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/auth/routers/session_router.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/nosql/mongo/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/db/nosql/mongo/crud_router.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/__init__.py
RENAMED
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/catchall.py
RENAMED
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/exceptions.py
RENAMED
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/errors/handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svc_infra-0.1.594 → svc_infra-0.1.595}/src/svc_infra/api/fastapi/middleware/request_size_limit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|