svc-infra 0.1.618__tar.gz → 0.1.704__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.704/LICENSE +21 -0
- svc_infra-0.1.704/PKG-INFO +350 -0
- svc_infra-0.1.704/README.md +271 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/pyproject.toml +64 -54
- svc_infra-0.1.704/src/svc_infra/__init__.py +33 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/models.py +133 -42
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/provider/aiydan.py +121 -47
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/provider/base.py +30 -9
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/provider/stripe.py +156 -62
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/schemas.py +18 -9
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/service.py +98 -41
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/settings.py +5 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/__init__.py +15 -0
- svc_infra-0.1.704/src/svc_infra/api/fastapi/admin/__init__.py +3 -0
- svc_infra-0.1.704/src/svc_infra/api/fastapi/admin/add.py +245 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/apf_payments/router.py +78 -30
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/apf_payments/setup.py +13 -6
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/_cookies.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/add.py +17 -14
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/gaurd.py +43 -14
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/mfa/models.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/mfa/pre_auth.py +10 -6
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/mfa/router.py +15 -8
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/mfa/security.py +1 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/mfa/utils.py +2 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/mfa/verify.py +9 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/policy.py +0 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/providers.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/routers/apikey_router.py +6 -6
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/routers/oauth_router.py +144 -45
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/routers/session_router.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/security.py +31 -10
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/sender.py +8 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/state.py +3 -1
- svc_infra-0.1.704/src/svc_infra/api/fastapi/auth/ws_security.py +275 -0
- svc_infra-0.1.704/src/svc_infra/api/fastapi/billing/router.py +73 -0
- svc_infra-0.1.704/src/svc_infra/api/fastapi/billing/setup.py +19 -0
- svc_infra-0.1.704/src/svc_infra/api/fastapi/cache/add.py +18 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/__init__.py +5 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/http.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/nosql/mongo/add.py +47 -32
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/nosql/mongo/crud_router.py +22 -10
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/sql/__init__.py +5 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/sql/add.py +39 -13
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/sql/crud_router.py +74 -48
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/sql/health.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/sql/session.py +18 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/sql/users.py +18 -6
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/dependencies/ratelimit.py +25 -11
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/docs/add.py +21 -8
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/docs/landing.py +4 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/docs/scoped.py +62 -15
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/dual/__init__.py +12 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/dual/dualize.py +1 -1
- svc_infra-0.1.704/src/svc_infra/api/fastapi/dual/protected.py +218 -0
- svc_infra-0.1.704/src/svc_infra/api/fastapi/dual/public.py +47 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/dual/router.py +40 -13
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/dx.py +33 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/ease.py +10 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/http/concurrency.py +2 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/http/conditional.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/debug.py +4 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/errors/catchall.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/errors/exceptions.py +1 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/errors/handlers.py +27 -4
- svc_infra-0.1.704/src/svc_infra/api/fastapi/middleware/graceful_shutdown.py +104 -0
- svc_infra-0.1.704/src/svc_infra/api/fastapi/middleware/idempotency.py +213 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/optimistic_lock.py +8 -3
- svc_infra-0.1.704/src/svc_infra/api/fastapi/middleware/ratelimit.py +158 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/ratelimit_store.py +43 -10
- svc_infra-0.1.704/src/svc_infra/api/fastapi/middleware/request_id.py +39 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/request_size_limit.py +3 -3
- svc_infra-0.1.704/src/svc_infra/api/fastapi/middleware/timeout.py +177 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/apply.py +5 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/conventions.py +9 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/mutators.py +56 -22
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/pipeline.py +1 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/security.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/ops/add.py +12 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/pagination.py +44 -19
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/routers/__init__.py +43 -15
- svc_infra-0.1.704/src/svc_infra/api/fastapi/setup.py +407 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/tenancy/context.py +3 -3
- svc_infra-0.1.704/src/svc_infra/api/fastapi/versioned.py +101 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/__init__.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/env.py +69 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/logging/add.py +9 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/logging/formats.py +12 -5
- svc_infra-0.1.704/src/svc_infra/billing/async_service.py +147 -0
- svc_infra-0.1.704/src/svc_infra/billing/jobs.py +241 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/billing/models.py +69 -23
- svc_infra-0.1.704/src/svc_infra/billing/quotas.py +103 -0
- svc_infra-0.1.704/src/svc_infra/billing/schemas.py +36 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/billing/service.py +10 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/__init__.py +9 -0
- svc_infra-0.1.704/src/svc_infra/cache/add.py +170 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/backend.py +2 -4
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/decorators.py +81 -33
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/demo.py +2 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/recache.py +26 -14
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/resources.py +14 -5
- svc_infra-0.1.704/src/svc_infra/cache/tags.py +52 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/utils.py +3 -1
- svc_infra-0.1.704/src/svc_infra/cli/__init__.py +79 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/__init__.py +7 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/nosql/mongo/mongo_cmds.py +7 -4
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/nosql/mongo/mongo_scaffold_cmds.py +7 -5
- svc_infra-0.1.704/src/svc_infra/cli/cmds/db/ops_cmds.py +270 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/sql/alembic_cmds.py +52 -20
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/sql/sql_export_cmds.py +20 -14
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/sql/sql_scaffold_cmds.py +3 -3
- svc_infra-0.1.704/src/svc_infra/cli/cmds/docs/docs_cmds.py +142 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/dx/dx_cmds.py +22 -5
- svc_infra-0.1.704/src/svc_infra/cli/cmds/health/__init__.py +179 -0
- svc_infra-0.1.704/src/svc_infra/cli/cmds/health/health_cmds.py +8 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/help.py +4 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/jobs/jobs_cmds.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/obs/obs_cmds.py +36 -15
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/sdk/sdk_cmds.py +15 -5
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/foundation/runner.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/data/add.py +2 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/data/backup.py +7 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/data/erasure.py +1 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/data/fixtures.py +5 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/data/retention.py +11 -5
- svc_infra-0.1.704/src/svc_infra/db/__init__.py +15 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/crud_schema.py +9 -9
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/core.py +18 -5
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/indexes.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/management.py +1 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/mongo/README.md +13 -13
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/mongo/settings.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/repository.py +17 -13
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/scaffold.py +9 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/service.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/types.py +6 -2
- svc_infra-0.1.704/src/svc_infra/db/ops.py +384 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/outbox.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/apikey.py +37 -9
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/authref.py +9 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/constants.py +12 -8
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/core.py +2 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/management.py +11 -8
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/repository.py +52 -17
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/scaffold.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/service.py +15 -5
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/models_schemas/auth/models.py.tmpl +7 -56
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/setup/env_async.py.tmpl +25 -11
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/setup/env_sync.py.tmpl +20 -5
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/tenant.py +13 -4
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/uniq_hooks.py +9 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/utils.py +138 -51
- svc_infra-0.1.704/src/svc_infra/deploy/__init__.py +538 -0
- svc_infra-0.1.704/src/svc_infra/documents/__init__.py +100 -0
- svc_infra-0.1.704/src/svc_infra/documents/add.py +264 -0
- svc_infra-0.1.704/src/svc_infra/documents/ease.py +233 -0
- svc_infra-0.1.704/src/svc_infra/documents/models.py +114 -0
- svc_infra-0.1.704/src/svc_infra/documents/storage.py +264 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/dx/add.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/dx/checks.py +3 -2
- svc_infra-0.1.704/src/svc_infra/exceptions.py +141 -0
- svc_infra-0.1.704/src/svc_infra/health/__init__.py +864 -0
- svc_infra-0.1.704/src/svc_infra/http/__init__.py +13 -0
- svc_infra-0.1.704/src/svc_infra/http/client.py +105 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/jobs/builtins/outbox_processor.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/jobs/builtins/webhook_delivery.py +21 -4
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/jobs/easy.py +1 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/jobs/loader.py +10 -5
- svc_infra-0.1.704/src/svc_infra/jobs/queue.py +116 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/jobs/redis_queue.py +87 -22
- svc_infra-0.1.704/src/svc_infra/jobs/runner.py +79 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/jobs/scheduler.py +13 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/jobs/worker.py +17 -1
- svc_infra-0.1.704/src/svc_infra/loaders/__init__.py +186 -0
- svc_infra-0.1.704/src/svc_infra/loaders/base.py +142 -0
- svc_infra-0.1.704/src/svc_infra/loaders/github.py +311 -0
- svc_infra-0.1.704/src/svc_infra/loaders/models.py +147 -0
- svc_infra-0.1.704/src/svc_infra/loaders/url.py +235 -0
- svc_infra-0.1.704/src/svc_infra/logging/__init__.py +374 -0
- svc_infra-0.1.704/src/svc_infra/mcp/svc_infra_mcp.py +125 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/add.py +13 -4
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/cloud_dash.py +2 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/metrics/__init__.py +3 -4
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/metrics/asgi.py +13 -7
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/metrics/http.py +9 -5
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/metrics/sqlalchemy.py +13 -9
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/metrics.py +6 -5
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/settings.py +6 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/add.py +23 -7
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/audit.py +92 -10
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/audit_service.py +4 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/headers.py +15 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/hibp.py +14 -4
- svc_infra-0.1.704/src/svc_infra/security/jwt_rotation.py +105 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/lockout.py +11 -5
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/models.py +54 -12
- svc_infra-0.1.704/src/svc_infra/security/oauth_models.py +73 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/org_invites.py +5 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/passwords.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/permissions.py +25 -2
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/session.py +1 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/security/signed_cookies.py +21 -1
- svc_infra-0.1.704/src/svc_infra/storage/__init__.py +93 -0
- svc_infra-0.1.704/src/svc_infra/storage/add.py +253 -0
- svc_infra-0.1.704/src/svc_infra/storage/backends/__init__.py +11 -0
- svc_infra-0.1.704/src/svc_infra/storage/backends/local.py +339 -0
- svc_infra-0.1.704/src/svc_infra/storage/backends/memory.py +216 -0
- svc_infra-0.1.704/src/svc_infra/storage/backends/s3.py +353 -0
- svc_infra-0.1.704/src/svc_infra/storage/base.py +239 -0
- svc_infra-0.1.704/src/svc_infra/storage/easy.py +185 -0
- svc_infra-0.1.704/src/svc_infra/storage/settings.py +195 -0
- svc_infra-0.1.704/src/svc_infra/testing/__init__.py +685 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/utils.py +7 -3
- svc_infra-0.1.704/src/svc_infra/webhooks/__init__.py +79 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/webhooks/add.py +65 -48
- svc_infra-0.1.704/src/svc_infra/webhooks/encryption.py +115 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/webhooks/fastapi.py +3 -1
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/webhooks/service.py +14 -3
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/webhooks/signing.py +5 -1
- svc_infra-0.1.704/src/svc_infra/websocket/__init__.py +79 -0
- svc_infra-0.1.704/src/svc_infra/websocket/add.py +140 -0
- svc_infra-0.1.704/src/svc_infra/websocket/client.py +282 -0
- svc_infra-0.1.704/src/svc_infra/websocket/config.py +69 -0
- svc_infra-0.1.704/src/svc_infra/websocket/easy.py +76 -0
- svc_infra-0.1.704/src/svc_infra/websocket/exceptions.py +61 -0
- svc_infra-0.1.704/src/svc_infra/websocket/manager.py +344 -0
- svc_infra-0.1.704/src/svc_infra/websocket/models.py +49 -0
- svc_infra-0.1.618/PKG-INFO +0 -131
- svc_infra-0.1.618/README.md +0 -54
- svc_infra-0.1.618/docs/acceptance-matrix.md +0 -71
- svc_infra-0.1.618/docs/acceptance.md +0 -44
- svc_infra-0.1.618/docs/adr/0002-background-jobs-and-scheduling.md +0 -40
- svc_infra-0.1.618/docs/adr/0003-webhooks-framework.md +0 -24
- svc_infra-0.1.618/docs/adr/0004-tenancy-model.md +0 -42
- svc_infra-0.1.618/docs/adr/0005-data-lifecycle.md +0 -86
- svc_infra-0.1.618/docs/adr/0006-ops-slos-and-metrics.md +0 -47
- svc_infra-0.1.618/docs/adr/0007-docs-and-sdks.md +0 -83
- svc_infra-0.1.618/docs/adr/0008-billing-primitives.md +0 -109
- svc_infra-0.1.618/docs/adr/0009-acceptance-harness.md +0 -40
- svc_infra-0.1.618/docs/api.md +0 -59
- svc_infra-0.1.618/docs/auth.md +0 -11
- svc_infra-0.1.618/docs/cache.md +0 -18
- svc_infra-0.1.618/docs/cli.md +0 -74
- svc_infra-0.1.618/docs/contributing.md +0 -34
- svc_infra-0.1.618/docs/data-lifecycle.md +0 -52
- svc_infra-0.1.618/docs/database.md +0 -14
- svc_infra-0.1.618/docs/docs-and-sdks.md +0 -62
- svc_infra-0.1.618/docs/environment.md +0 -114
- svc_infra-0.1.618/docs/idempotency.md +0 -111
- svc_infra-0.1.618/docs/jobs.md +0 -67
- svc_infra-0.1.618/docs/observability.md +0 -16
- svc_infra-0.1.618/docs/ops.md +0 -33
- svc_infra-0.1.618/docs/rate-limiting.md +0 -121
- svc_infra-0.1.618/docs/repo-review.md +0 -48
- svc_infra-0.1.618/docs/security.md +0 -155
- svc_infra-0.1.618/docs/tenancy.md +0 -35
- svc_infra-0.1.618/docs/webhooks.md +0 -112
- svc_infra-0.1.618/src/svc_infra/__init__.py +0 -3
- svc_infra-0.1.618/src/svc_infra/api/fastapi/cache/add.py +0 -14
- svc_infra-0.1.618/src/svc_infra/api/fastapi/dual/protected.py +0 -96
- svc_infra-0.1.618/src/svc_infra/api/fastapi/dual/public.py +0 -22
- svc_infra-0.1.618/src/svc_infra/api/fastapi/middleware/idempotency.py +0 -116
- svc_infra-0.1.618/src/svc_infra/api/fastapi/middleware/ratelimit.py +0 -109
- svc_infra-0.1.618/src/svc_infra/api/fastapi/middleware/request_id.py +0 -23
- svc_infra-0.1.618/src/svc_infra/api/fastapi/setup.py +0 -276
- svc_infra-0.1.618/src/svc_infra/cache/tags.py +0 -77
- svc_infra-0.1.618/src/svc_infra/cli/__init__.py +0 -53
- svc_infra-0.1.618/src/svc_infra/cli/cmds/docs/docs_cmds.py +0 -188
- svc_infra-0.1.618/src/svc_infra/jobs/queue.py +0 -73
- svc_infra-0.1.618/src/svc_infra/mcp/svc_infra_mcp.py +0 -67
- svc_infra-0.1.618/src/svc_infra/obs/templates/sidecars/railway/__init__.py +0 -0
- svc_infra-0.1.618/src/svc_infra/security/jwt_rotation.py +0 -53
- svc_infra-0.1.618/src/svc_infra/webhooks/__init__.py +0 -16
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/alembic.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/provider/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/apf_payments/provider/registry.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/apf_payments/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/mfa/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/routers/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/routers/account.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/auth/settings.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/cache/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/nosql/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/nosql/mongo/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/nosql/mongo/health.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/db/sql/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/docs/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/dual/utils.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/http/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/http/deprecation.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/errors/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/middleware/idempotency_store.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/models.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/openapi/responses.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/paths/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/paths/auth.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/paths/generic.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/paths/prefix.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/paths/user.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/routers/ping.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/api/fastapi/tenancy/add.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/logging/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/logging/filter.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/app/root.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/billing/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/bundled_docs/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/bundled_docs/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/bundled_docs/getting-started.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/keys.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cache/ttl.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/__main__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/nosql/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/nosql/mongo/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/nosql/mongo/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/db/sql/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/dx/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/jobs/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/obs/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/cmds/sdk/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/foundation/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/cli/foundation/typer_bootstrap.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/inbox.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/base.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/constants.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/db → svc_infra-0.1.704/src/svc_infra/db/nosql/mongo}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/mongo/client.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/db/nosql/mongo → svc_infra-0.1.704/src/svc_infra/db/nosql/mongo/templates}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/mongo/templates/documents.py.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/mongo/templates/resources.py.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/mongo/templates/schemas.py.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/resource.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/service_with_hooks.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/nosql/utils.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/base.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/resource.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/service_with_hooks.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/__init__.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/db/nosql/mongo/templates → svc_infra-0.1.704/src/svc_infra/db/sql/templates/models_schemas}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/models_schemas/auth/schemas.py.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/models_schemas/entity/models.py.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/models_schemas/entity/schemas.py.tmpl +0 -0
- {svc_infra-0.1.618/src/svc_infra/db/sql/templates/models_schemas → svc_infra-0.1.704/src/svc_infra/db/sql/templates/setup}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/setup/alembic.ini.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/templates/setup/script.py.mako.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/types.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/uniq.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/sql/versioning.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/db/utils.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/dx/changelog.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/db/sql/templates/setup → svc_infra-0.1.704/src/svc_infra/mcp}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/README.md +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/grafana/dashboards/http-overview.json +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/metrics/base.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/mcp → svc_infra-0.1.704/src/svc_infra/obs/providers}/__init__.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/providers → svc_infra-0.1.704/src/svc_infra/obs/providers/compose_cloud}/__init__.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/providers/compose_cloud → svc_infra-0.1.704/src/svc_infra/obs/providers/compose_cloud/templates}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/compose_cloud/templates/agent.yaml.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/compose_cloud/templates/docker-compose.cloud.yml.tmpl +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/providers/compose_cloud/templates → svc_infra-0.1.704/src/svc_infra/obs/providers/grafana}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/dashboards/00_overview.json +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/dashboards/10_http.json +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/dashboards/20_db.json +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/dashboards/30_runtime.json +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/dashboards/40_clients.json +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/providers/grafana → svc_infra-0.1.704/src/svc_infra/obs/providers/grafana/dashboards}/__init__.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/providers/grafana/dashboards → svc_infra-0.1.704/src/svc_infra/obs/providers/grafana/templates}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/templates/docker-compose.yml.tmpl +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/templates/prometheus.yml.tmpl +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/providers/grafana/templates → svc_infra-0.1.704/src/svc_infra/obs/providers/grafana/templates/provisioning}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/templates/provisioning/dashboards.yml +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/providers/grafana/templates/provisioning/datasource.yml +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/grafana_dashboard.json +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/prometheus_rules.yml +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/providers/grafana/templates/provisioning → svc_infra-0.1.704/src/svc_infra/obs/templates/sidecars}/__init__.py +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/templates/sidecars → svc_infra-0.1.704/src/svc_infra/obs/templates/sidecars/compose}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/compose/agent.yaml +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/compose/docker-compose.yml +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/templates/sidecars/compose → svc_infra-0.1.704/src/svc_infra/obs/templates/sidecars/fly}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/fly/agent.yaml +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/fly/fly.toml.fragment +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/templates/sidecars/fly → svc_infra-0.1.704/src/svc_infra/obs/templates/sidecars/k8s}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/k8s/configmap.yaml +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/k8s/deployment.yaml +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/railway/Dockerfile +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/railway/README.md +0 -0
- {svc_infra-0.1.618/src/svc_infra/obs/templates/sidecars/k8s → svc_infra-0.1.704/src/svc_infra/obs/templates/sidecars/railway}/__init__.py +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/obs/templates/sidecars/railway/agent.yaml +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/py.typed +0 -0
- {svc_infra-0.1.618 → svc_infra-0.1.704}/src/svc_infra/webhooks/router.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 nfrax
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: svc-infra
|
|
3
|
+
Version: 0.1.704
|
|
4
|
+
Summary: Infrastructure for building and deploying prod-ready services
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: fastapi,sqlalchemy,alembic,auth,infra,async,pydantic
|
|
7
|
+
Author: Ali Khatami
|
|
8
|
+
Author-email: aliikhatami94@gmail.com
|
|
9
|
+
Requires-Python: >=3.11,<4.0
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Framework :: FastAPI
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Provides-Extra: duckdb
|
|
21
|
+
Provides-Extra: metrics
|
|
22
|
+
Provides-Extra: mssql
|
|
23
|
+
Provides-Extra: mysql
|
|
24
|
+
Provides-Extra: pg
|
|
25
|
+
Provides-Extra: pg2
|
|
26
|
+
Provides-Extra: redshift
|
|
27
|
+
Provides-Extra: s3
|
|
28
|
+
Provides-Extra: snowflake
|
|
29
|
+
Provides-Extra: sqlite
|
|
30
|
+
Requires-Dist: adyen (>=10.0.0)
|
|
31
|
+
Requires-Dist: aioboto3 (>=12.0.0) ; extra == "s3"
|
|
32
|
+
Requires-Dist: aiofiles (>=24.0.0)
|
|
33
|
+
Requires-Dist: aiosqlite (>=0.19.0) ; extra == "sqlite"
|
|
34
|
+
Requires-Dist: alembic (>=1.13.0)
|
|
35
|
+
Requires-Dist: asyncpg (>=0.29.0) ; extra == "pg"
|
|
36
|
+
Requires-Dist: authlib (>=1.0.0)
|
|
37
|
+
Requires-Dist: cashews[redis] (>=7.0)
|
|
38
|
+
Requires-Dist: duckdb (>=0.10.0) ; extra == "duckdb"
|
|
39
|
+
Requires-Dist: email-validator (>=2.0.0)
|
|
40
|
+
Requires-Dist: fastapi (>=0.110.0)
|
|
41
|
+
Requires-Dist: fastapi-users-db-sqlalchemy (>=7.0.0)
|
|
42
|
+
Requires-Dist: fastapi-users[oauth] (>=14.0.0)
|
|
43
|
+
Requires-Dist: greenlet (>=3.0)
|
|
44
|
+
Requires-Dist: httpx (>=0.25.0)
|
|
45
|
+
Requires-Dist: httpx-oauth (>=0.15.0)
|
|
46
|
+
Requires-Dist: itsdangerous (>=2.0.0)
|
|
47
|
+
Requires-Dist: mcp (>=1.0.0)
|
|
48
|
+
Requires-Dist: motor (>=3.0.0)
|
|
49
|
+
Requires-Dist: mysqlclient (>=2.2.0) ; extra == "mysql"
|
|
50
|
+
Requires-Dist: opentelemetry-exporter-otlp (>=1.20.0)
|
|
51
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.41b0)
|
|
52
|
+
Requires-Dist: opentelemetry-instrumentation-httpx (>=0.41b0)
|
|
53
|
+
Requires-Dist: opentelemetry-instrumentation-requests (>=0.41b0)
|
|
54
|
+
Requires-Dist: opentelemetry-instrumentation-sqlalchemy (>=0.41b0)
|
|
55
|
+
Requires-Dist: opentelemetry-propagator-b3 (>=1.20.0)
|
|
56
|
+
Requires-Dist: opentelemetry-sdk (>=1.20.0)
|
|
57
|
+
Requires-Dist: passlib[bcrypt] (>=1.7.4)
|
|
58
|
+
Requires-Dist: prometheus-client (>=0.18.0) ; extra == "metrics"
|
|
59
|
+
Requires-Dist: psycopg2-binary (>=2.9.0) ; extra == "pg2"
|
|
60
|
+
Requires-Dist: psycopg[binary] (>=3.0) ; extra == "pg"
|
|
61
|
+
Requires-Dist: pydantic-settings (>=2.0)
|
|
62
|
+
Requires-Dist: pymysql (>=1.1.0) ; extra == "mysql"
|
|
63
|
+
Requires-Dist: pyodbc (>=5.0.0) ; extra == "mssql"
|
|
64
|
+
Requires-Dist: pyotp (>=2.9.0)
|
|
65
|
+
Requires-Dist: python-dotenv (>=1.0.0)
|
|
66
|
+
Requires-Dist: redis (>=5.0.0)
|
|
67
|
+
Requires-Dist: redshift-connector (>=2.0.0) ; extra == "redshift"
|
|
68
|
+
Requires-Dist: snowflake-connector-python (>=3.0.0) ; extra == "snowflake"
|
|
69
|
+
Requires-Dist: sqlalchemy[asyncio] (>=2.0)
|
|
70
|
+
Requires-Dist: stripe (>=7.0.0)
|
|
71
|
+
Requires-Dist: typer (>=0.12.0)
|
|
72
|
+
Requires-Dist: websockets (>=12.0)
|
|
73
|
+
Project-URL: Documentation, https://github.com/your-org/svc-infra#readme
|
|
74
|
+
Project-URL: Homepage, https://github.com/your-org/svc-infra
|
|
75
|
+
Project-URL: Issues, https://github.com/your-org/svc-infra/issues
|
|
76
|
+
Project-URL: Repository, https://github.com/your-org/svc-infra
|
|
77
|
+
Description-Content-Type: text/markdown
|
|
78
|
+
|
|
79
|
+
<div align="center">
|
|
80
|
+
|
|
81
|
+
# svc-infra
|
|
82
|
+
|
|
83
|
+
### Production-ready FastAPI infrastructure in one import
|
|
84
|
+
|
|
85
|
+
[](https://pypi.org/project/svc-infra/) [](https://www.python.org/downloads/) [](https://opensource.org/licenses/MIT) [](https://pepy.tech/project/svc-infra)
|
|
86
|
+
|
|
87
|
+
**Stop rebuilding auth, billing, webhooks, and background jobs for every project.**
|
|
88
|
+
|
|
89
|
+
[Documentation](docs/) · [Examples](examples/) · [PyPI](https://pypi.org/project/svc-infra/)
|
|
90
|
+
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Why svc-infra?
|
|
96
|
+
|
|
97
|
+
Every FastAPI project needs the same things: authentication, database setup, background jobs, caching, webhooks, billing... You've written this code before. Multiple times.
|
|
98
|
+
|
|
99
|
+
**svc-infra** packages battle-tested infrastructure used in production, so you can focus on your actual product:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from svc_infra.api.fastapi.ease import easy_service_app
|
|
103
|
+
|
|
104
|
+
app = easy_service_app(name="MyAPI", release="1.0.0")
|
|
105
|
+
# ✅ Health checks, CORS, security headers, structured logging
|
|
106
|
+
# ✅ Prometheus metrics, OpenTelemetry tracing
|
|
107
|
+
# ✅ Request IDs, idempotency middleware
|
|
108
|
+
# That's it. Ship it.
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## ⚡ Quick Install
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install svc-infra
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 🎯 What's Included
|
|
118
|
+
|
|
119
|
+
| Feature | What You Get | One-liner |
|
|
120
|
+
|---------|-------------|-----------|
|
|
121
|
+
| **🔐 Auth** | JWT, sessions, OAuth/OIDC, MFA, API keys | `add_auth_users(app)` |
|
|
122
|
+
| **💳 Billing** | Usage tracking, subscriptions, invoices, Stripe sync | `add_billing(app)` |
|
|
123
|
+
| **📦 Database** | PostgreSQL + MongoDB, migrations, inbox/outbox | `add_sql_db(app)` |
|
|
124
|
+
| **⚡ Jobs** | Background tasks, scheduling, retries, DLQ | `easy_jobs()` |
|
|
125
|
+
| **🔗 Webhooks** | Subscriptions, HMAC signing, delivery retries | `add_webhooks(app)` |
|
|
126
|
+
| **💾 Cache** | Redis/memory, decorators, namespacing | `init_cache()` |
|
|
127
|
+
| **📊 Observability** | Prometheus, Grafana dashboards, OTEL | Built-in |
|
|
128
|
+
| **📁 Storage** | S3, local, memory backends | `add_storage(app)` |
|
|
129
|
+
| **🏢 Multi-tenancy** | Tenant isolation, scoped queries | Built-in |
|
|
130
|
+
| **🚦 Rate Limiting** | Per-user, per-endpoint, headers | Built-in |
|
|
131
|
+
|
|
132
|
+
## 🚀 30-Second Example
|
|
133
|
+
|
|
134
|
+
Build a complete SaaS backend:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from fastapi import Depends
|
|
138
|
+
from svc_infra.api.fastapi.ease import easy_service_app
|
|
139
|
+
from svc_infra.api.fastapi.db.sql.add import add_sql_db
|
|
140
|
+
from svc_infra.api.fastapi.auth import add_auth_users, current_active_user
|
|
141
|
+
from svc_infra.jobs.easy import easy_jobs
|
|
142
|
+
from svc_infra.webhooks.fastapi import require_signature
|
|
143
|
+
|
|
144
|
+
# Create app with batteries included
|
|
145
|
+
app = easy_service_app(name="MySaaS", release="1.0.0")
|
|
146
|
+
|
|
147
|
+
# Add infrastructure
|
|
148
|
+
add_sql_db(app) # PostgreSQL with migrations
|
|
149
|
+
add_auth_users(app) # Full auth system
|
|
150
|
+
queue, scheduler = easy_jobs() # Background jobs
|
|
151
|
+
|
|
152
|
+
# Your actual business logic
|
|
153
|
+
@app.post("/api/process")
|
|
154
|
+
async def process_data(user=Depends(current_active_user)):
|
|
155
|
+
job = queue.enqueue("heavy_task", {"user_id": user.id})
|
|
156
|
+
return {"job_id": job.id, "status": "queued"}
|
|
157
|
+
|
|
158
|
+
# Webhook endpoint with signature verification
|
|
159
|
+
@app.post("/webhooks/stripe")
|
|
160
|
+
async def stripe_webhook(payload=Depends(require_signature(lambda: ["whsec_..."]))):
|
|
161
|
+
queue.enqueue("process_payment", payload)
|
|
162
|
+
return {"received": True}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**That's a production-ready API** with auth, database, background jobs, and webhook handling.
|
|
166
|
+
|
|
167
|
+
## 📚 Feature Highlights
|
|
168
|
+
|
|
169
|
+
### 🔐 Authentication & Security
|
|
170
|
+
|
|
171
|
+
Full auth system with zero boilerplate:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from svc_infra.api.fastapi.auth import add_auth_users, current_active_user
|
|
175
|
+
|
|
176
|
+
add_auth_users(app) # Registers /auth/* routes automatically
|
|
177
|
+
|
|
178
|
+
@app.get("/me")
|
|
179
|
+
async def get_profile(user=Depends(current_active_user)):
|
|
180
|
+
return {"email": user.email, "mfa_enabled": user.mfa_enabled}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Includes:** JWT tokens, session cookies, OAuth/OIDC (Google, GitHub, etc.), MFA/TOTP, password policies, account lockout, key rotation.
|
|
184
|
+
|
|
185
|
+
### 💳 Usage-Based Billing
|
|
186
|
+
|
|
187
|
+
Track usage and generate invoices:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from svc_infra.billing import BillingService
|
|
191
|
+
|
|
192
|
+
billing = BillingService(session=db, tenant_id="tenant_123")
|
|
193
|
+
|
|
194
|
+
# Record API usage (idempotent)
|
|
195
|
+
billing.record_usage(metric="api_calls", amount=1, idempotency_key="req_abc")
|
|
196
|
+
|
|
197
|
+
# Generate monthly invoice
|
|
198
|
+
invoice = billing.generate_monthly_invoice(
|
|
199
|
+
period_start=datetime(2025, 1, 1),
|
|
200
|
+
period_end=datetime(2025, 2, 1),
|
|
201
|
+
)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Includes:** Usage events, aggregation, plans & entitlements, subscriptions, invoices, Stripe sync hooks.
|
|
205
|
+
|
|
206
|
+
### ⚡ Background Jobs
|
|
207
|
+
|
|
208
|
+
Redis-backed job queue with retries:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from svc_infra.jobs.easy import easy_jobs
|
|
212
|
+
|
|
213
|
+
queue, scheduler = easy_jobs() # Auto-detects Redis or uses memory
|
|
214
|
+
|
|
215
|
+
# Enqueue work
|
|
216
|
+
queue.enqueue("send_email", {"to": "user@example.com", "template": "welcome"})
|
|
217
|
+
|
|
218
|
+
# Schedule recurring tasks
|
|
219
|
+
scheduler.add("cleanup", interval_seconds=3600, target="myapp.tasks:cleanup")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Run the worker
|
|
224
|
+
svc-infra jobs run
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Includes:** Visibility timeout, exponential backoff, dead letter queue, interval scheduler, CLI worker.
|
|
228
|
+
|
|
229
|
+
### 🔗 Webhooks
|
|
230
|
+
|
|
231
|
+
Send and receive webhooks with proper security:
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
from svc_infra.webhooks import add_webhooks, WebhookService
|
|
235
|
+
|
|
236
|
+
add_webhooks(app) # Adds subscription management routes
|
|
237
|
+
|
|
238
|
+
# Publish events
|
|
239
|
+
webhook_service.publish("invoice.paid", {"invoice_id": "inv_123"})
|
|
240
|
+
|
|
241
|
+
# Verify incoming webhooks
|
|
242
|
+
@app.post("/webhooks/external")
|
|
243
|
+
async def receive(payload=Depends(require_signature(lambda: ["secret1", "secret2"]))):
|
|
244
|
+
return {"ok": True}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Includes:** Subscription store, HMAC-SHA256 signing, delivery retries, idempotent processing.
|
|
248
|
+
|
|
249
|
+
### 📊 Observability
|
|
250
|
+
|
|
251
|
+
Production monitoring out of the box:
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
app = easy_service_app(name="MyAPI", release="1.0.0")
|
|
255
|
+
# Prometheus metrics at /metrics
|
|
256
|
+
# Health checks at /healthz, /readyz, /startupz
|
|
257
|
+
# Request tracing with OpenTelemetry
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# Generate Grafana dashboards
|
|
262
|
+
svc-infra obs dashboard --service myapi --output ./dashboards/
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Includes:** Prometheus metrics, Grafana dashboard generator, OTEL integration, SLO helpers.
|
|
266
|
+
|
|
267
|
+
## ⚙️ Configuration
|
|
268
|
+
|
|
269
|
+
Everything is configurable via environment variables:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Database
|
|
273
|
+
SQL_URL=postgresql://user:pass@localhost/mydb
|
|
274
|
+
MONGO_URL=mongodb://localhost:27017
|
|
275
|
+
|
|
276
|
+
# Auth
|
|
277
|
+
AUTH_JWT__SECRET=your-secret-key
|
|
278
|
+
AUTH_SMTP_HOST=smtp.sendgrid.net
|
|
279
|
+
|
|
280
|
+
# Jobs
|
|
281
|
+
JOBS_DRIVER=redis
|
|
282
|
+
REDIS_URL=redis://localhost:6379
|
|
283
|
+
|
|
284
|
+
# Storage
|
|
285
|
+
STORAGE_BACKEND=s3
|
|
286
|
+
STORAGE_S3_BUCKET=my-uploads
|
|
287
|
+
|
|
288
|
+
# Observability
|
|
289
|
+
ENABLE_OBS=true
|
|
290
|
+
METRICS_PATH=/metrics
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
See the [Environment Reference](docs/environment.md) for all options.
|
|
294
|
+
|
|
295
|
+
## 📖 Documentation
|
|
296
|
+
|
|
297
|
+
| Module | Description | Guide |
|
|
298
|
+
|--------|-------------|-------|
|
|
299
|
+
| **API** | FastAPI bootstrap, middleware, versioning | [docs/api.md](docs/api.md) |
|
|
300
|
+
| **Auth** | Sessions, OAuth/OIDC, MFA, API keys | [docs/auth.md](docs/auth.md) |
|
|
301
|
+
| **Billing** | Usage tracking, subscriptions, invoices | [docs/billing.md](docs/billing.md) |
|
|
302
|
+
| **Database** | SQL + MongoDB, migrations, patterns | [docs/database.md](docs/database.md) |
|
|
303
|
+
| **Jobs** | Background tasks, scheduling | [docs/jobs.md](docs/jobs.md) |
|
|
304
|
+
| **Webhooks** | Publishing, signing, verification | [docs/webhooks.md](docs/webhooks.md) |
|
|
305
|
+
| **Cache** | Redis/memory caching, TTL helpers | [docs/cache.md](docs/cache.md) |
|
|
306
|
+
| **Storage** | S3, local, memory file storage | [docs/storage.md](docs/storage.md) |
|
|
307
|
+
| **Observability** | Metrics, tracing, dashboards | [docs/observability.md](docs/observability.md) |
|
|
308
|
+
| **Security** | Password policy, headers, MFA | [docs/security.md](docs/security.md) |
|
|
309
|
+
| **Tenancy** | Multi-tenant isolation | [docs/tenancy.md](docs/tenancy.md) |
|
|
310
|
+
| **CLI** | Command-line tools | [docs/cli.md](docs/cli.md) |
|
|
311
|
+
|
|
312
|
+
## 🏃 Running the Example
|
|
313
|
+
|
|
314
|
+
See all features working together:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
git clone https://github.com/nfraxlab/svc-infra.git
|
|
318
|
+
cd svc-infra
|
|
319
|
+
|
|
320
|
+
# Setup and run
|
|
321
|
+
make setup-template # Creates DB, runs migrations
|
|
322
|
+
make run-template # Starts at http://localhost:8001
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Visit http://localhost:8001/docs to explore the API.
|
|
326
|
+
|
|
327
|
+
## 🤝 Related Packages
|
|
328
|
+
|
|
329
|
+
svc-infra is part of the **nfrax** infrastructure suite:
|
|
330
|
+
|
|
331
|
+
| Package | Purpose |
|
|
332
|
+
|---------|---------|
|
|
333
|
+
| **[svc-infra](https://github.com/nfraxlab/svc-infra)** | Backend infrastructure (auth, billing, jobs, webhooks) |
|
|
334
|
+
| **[ai-infra](https://github.com/nfraxlab/ai-infra)** | AI/LLM infrastructure (agents, tools, RAG, MCP) |
|
|
335
|
+
| **[fin-infra](https://github.com/nfraxlab/fin-infra)** | Financial infrastructure (banking, portfolio, insights) |
|
|
336
|
+
|
|
337
|
+
## 📄 License
|
|
338
|
+
|
|
339
|
+
MIT License - use it for anything.
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
<div align="center">
|
|
344
|
+
|
|
345
|
+
**Built with ❤️ by [nfraxlab](https://github.com/nfraxlab)**
|
|
346
|
+
|
|
347
|
+
[⭐ Star us on GitHub](https://github.com/nfraxlab/svc-infra) · [📦 View on PyPI](https://pypi.org/project/svc-infra/)
|
|
348
|
+
|
|
349
|
+
</div>
|
|
350
|
+
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# svc-infra
|
|
4
|
+
|
|
5
|
+
### Production-ready FastAPI infrastructure in one import
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/svc-infra/) [](https://www.python.org/downloads/) [](https://opensource.org/licenses/MIT) [](https://pepy.tech/project/svc-infra)
|
|
8
|
+
|
|
9
|
+
**Stop rebuilding auth, billing, webhooks, and background jobs for every project.**
|
|
10
|
+
|
|
11
|
+
[Documentation](docs/) · [Examples](examples/) · [PyPI](https://pypi.org/project/svc-infra/)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Why svc-infra?
|
|
18
|
+
|
|
19
|
+
Every FastAPI project needs the same things: authentication, database setup, background jobs, caching, webhooks, billing... You've written this code before. Multiple times.
|
|
20
|
+
|
|
21
|
+
**svc-infra** packages battle-tested infrastructure used in production, so you can focus on your actual product:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from svc_infra.api.fastapi.ease import easy_service_app
|
|
25
|
+
|
|
26
|
+
app = easy_service_app(name="MyAPI", release="1.0.0")
|
|
27
|
+
# ✅ Health checks, CORS, security headers, structured logging
|
|
28
|
+
# ✅ Prometheus metrics, OpenTelemetry tracing
|
|
29
|
+
# ✅ Request IDs, idempotency middleware
|
|
30
|
+
# That's it. Ship it.
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## ⚡ Quick Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install svc-infra
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 🎯 What's Included
|
|
40
|
+
|
|
41
|
+
| Feature | What You Get | One-liner |
|
|
42
|
+
|---------|-------------|-----------|
|
|
43
|
+
| **🔐 Auth** | JWT, sessions, OAuth/OIDC, MFA, API keys | `add_auth_users(app)` |
|
|
44
|
+
| **💳 Billing** | Usage tracking, subscriptions, invoices, Stripe sync | `add_billing(app)` |
|
|
45
|
+
| **📦 Database** | PostgreSQL + MongoDB, migrations, inbox/outbox | `add_sql_db(app)` |
|
|
46
|
+
| **⚡ Jobs** | Background tasks, scheduling, retries, DLQ | `easy_jobs()` |
|
|
47
|
+
| **🔗 Webhooks** | Subscriptions, HMAC signing, delivery retries | `add_webhooks(app)` |
|
|
48
|
+
| **💾 Cache** | Redis/memory, decorators, namespacing | `init_cache()` |
|
|
49
|
+
| **📊 Observability** | Prometheus, Grafana dashboards, OTEL | Built-in |
|
|
50
|
+
| **📁 Storage** | S3, local, memory backends | `add_storage(app)` |
|
|
51
|
+
| **🏢 Multi-tenancy** | Tenant isolation, scoped queries | Built-in |
|
|
52
|
+
| **🚦 Rate Limiting** | Per-user, per-endpoint, headers | Built-in |
|
|
53
|
+
|
|
54
|
+
## 🚀 30-Second Example
|
|
55
|
+
|
|
56
|
+
Build a complete SaaS backend:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from fastapi import Depends
|
|
60
|
+
from svc_infra.api.fastapi.ease import easy_service_app
|
|
61
|
+
from svc_infra.api.fastapi.db.sql.add import add_sql_db
|
|
62
|
+
from svc_infra.api.fastapi.auth import add_auth_users, current_active_user
|
|
63
|
+
from svc_infra.jobs.easy import easy_jobs
|
|
64
|
+
from svc_infra.webhooks.fastapi import require_signature
|
|
65
|
+
|
|
66
|
+
# Create app with batteries included
|
|
67
|
+
app = easy_service_app(name="MySaaS", release="1.0.0")
|
|
68
|
+
|
|
69
|
+
# Add infrastructure
|
|
70
|
+
add_sql_db(app) # PostgreSQL with migrations
|
|
71
|
+
add_auth_users(app) # Full auth system
|
|
72
|
+
queue, scheduler = easy_jobs() # Background jobs
|
|
73
|
+
|
|
74
|
+
# Your actual business logic
|
|
75
|
+
@app.post("/api/process")
|
|
76
|
+
async def process_data(user=Depends(current_active_user)):
|
|
77
|
+
job = queue.enqueue("heavy_task", {"user_id": user.id})
|
|
78
|
+
return {"job_id": job.id, "status": "queued"}
|
|
79
|
+
|
|
80
|
+
# Webhook endpoint with signature verification
|
|
81
|
+
@app.post("/webhooks/stripe")
|
|
82
|
+
async def stripe_webhook(payload=Depends(require_signature(lambda: ["whsec_..."]))):
|
|
83
|
+
queue.enqueue("process_payment", payload)
|
|
84
|
+
return {"received": True}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**That's a production-ready API** with auth, database, background jobs, and webhook handling.
|
|
88
|
+
|
|
89
|
+
## 📚 Feature Highlights
|
|
90
|
+
|
|
91
|
+
### 🔐 Authentication & Security
|
|
92
|
+
|
|
93
|
+
Full auth system with zero boilerplate:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from svc_infra.api.fastapi.auth import add_auth_users, current_active_user
|
|
97
|
+
|
|
98
|
+
add_auth_users(app) # Registers /auth/* routes automatically
|
|
99
|
+
|
|
100
|
+
@app.get("/me")
|
|
101
|
+
async def get_profile(user=Depends(current_active_user)):
|
|
102
|
+
return {"email": user.email, "mfa_enabled": user.mfa_enabled}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Includes:** JWT tokens, session cookies, OAuth/OIDC (Google, GitHub, etc.), MFA/TOTP, password policies, account lockout, key rotation.
|
|
106
|
+
|
|
107
|
+
### 💳 Usage-Based Billing
|
|
108
|
+
|
|
109
|
+
Track usage and generate invoices:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from svc_infra.billing import BillingService
|
|
113
|
+
|
|
114
|
+
billing = BillingService(session=db, tenant_id="tenant_123")
|
|
115
|
+
|
|
116
|
+
# Record API usage (idempotent)
|
|
117
|
+
billing.record_usage(metric="api_calls", amount=1, idempotency_key="req_abc")
|
|
118
|
+
|
|
119
|
+
# Generate monthly invoice
|
|
120
|
+
invoice = billing.generate_monthly_invoice(
|
|
121
|
+
period_start=datetime(2025, 1, 1),
|
|
122
|
+
period_end=datetime(2025, 2, 1),
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Includes:** Usage events, aggregation, plans & entitlements, subscriptions, invoices, Stripe sync hooks.
|
|
127
|
+
|
|
128
|
+
### ⚡ Background Jobs
|
|
129
|
+
|
|
130
|
+
Redis-backed job queue with retries:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from svc_infra.jobs.easy import easy_jobs
|
|
134
|
+
|
|
135
|
+
queue, scheduler = easy_jobs() # Auto-detects Redis or uses memory
|
|
136
|
+
|
|
137
|
+
# Enqueue work
|
|
138
|
+
queue.enqueue("send_email", {"to": "user@example.com", "template": "welcome"})
|
|
139
|
+
|
|
140
|
+
# Schedule recurring tasks
|
|
141
|
+
scheduler.add("cleanup", interval_seconds=3600, target="myapp.tasks:cleanup")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Run the worker
|
|
146
|
+
svc-infra jobs run
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Includes:** Visibility timeout, exponential backoff, dead letter queue, interval scheduler, CLI worker.
|
|
150
|
+
|
|
151
|
+
### 🔗 Webhooks
|
|
152
|
+
|
|
153
|
+
Send and receive webhooks with proper security:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from svc_infra.webhooks import add_webhooks, WebhookService
|
|
157
|
+
|
|
158
|
+
add_webhooks(app) # Adds subscription management routes
|
|
159
|
+
|
|
160
|
+
# Publish events
|
|
161
|
+
webhook_service.publish("invoice.paid", {"invoice_id": "inv_123"})
|
|
162
|
+
|
|
163
|
+
# Verify incoming webhooks
|
|
164
|
+
@app.post("/webhooks/external")
|
|
165
|
+
async def receive(payload=Depends(require_signature(lambda: ["secret1", "secret2"]))):
|
|
166
|
+
return {"ok": True}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Includes:** Subscription store, HMAC-SHA256 signing, delivery retries, idempotent processing.
|
|
170
|
+
|
|
171
|
+
### 📊 Observability
|
|
172
|
+
|
|
173
|
+
Production monitoring out of the box:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
app = easy_service_app(name="MyAPI", release="1.0.0")
|
|
177
|
+
# Prometheus metrics at /metrics
|
|
178
|
+
# Health checks at /healthz, /readyz, /startupz
|
|
179
|
+
# Request tracing with OpenTelemetry
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Generate Grafana dashboards
|
|
184
|
+
svc-infra obs dashboard --service myapi --output ./dashboards/
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Includes:** Prometheus metrics, Grafana dashboard generator, OTEL integration, SLO helpers.
|
|
188
|
+
|
|
189
|
+
## ⚙️ Configuration
|
|
190
|
+
|
|
191
|
+
Everything is configurable via environment variables:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Database
|
|
195
|
+
SQL_URL=postgresql://user:pass@localhost/mydb
|
|
196
|
+
MONGO_URL=mongodb://localhost:27017
|
|
197
|
+
|
|
198
|
+
# Auth
|
|
199
|
+
AUTH_JWT__SECRET=your-secret-key
|
|
200
|
+
AUTH_SMTP_HOST=smtp.sendgrid.net
|
|
201
|
+
|
|
202
|
+
# Jobs
|
|
203
|
+
JOBS_DRIVER=redis
|
|
204
|
+
REDIS_URL=redis://localhost:6379
|
|
205
|
+
|
|
206
|
+
# Storage
|
|
207
|
+
STORAGE_BACKEND=s3
|
|
208
|
+
STORAGE_S3_BUCKET=my-uploads
|
|
209
|
+
|
|
210
|
+
# Observability
|
|
211
|
+
ENABLE_OBS=true
|
|
212
|
+
METRICS_PATH=/metrics
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
See the [Environment Reference](docs/environment.md) for all options.
|
|
216
|
+
|
|
217
|
+
## 📖 Documentation
|
|
218
|
+
|
|
219
|
+
| Module | Description | Guide |
|
|
220
|
+
|--------|-------------|-------|
|
|
221
|
+
| **API** | FastAPI bootstrap, middleware, versioning | [docs/api.md](docs/api.md) |
|
|
222
|
+
| **Auth** | Sessions, OAuth/OIDC, MFA, API keys | [docs/auth.md](docs/auth.md) |
|
|
223
|
+
| **Billing** | Usage tracking, subscriptions, invoices | [docs/billing.md](docs/billing.md) |
|
|
224
|
+
| **Database** | SQL + MongoDB, migrations, patterns | [docs/database.md](docs/database.md) |
|
|
225
|
+
| **Jobs** | Background tasks, scheduling | [docs/jobs.md](docs/jobs.md) |
|
|
226
|
+
| **Webhooks** | Publishing, signing, verification | [docs/webhooks.md](docs/webhooks.md) |
|
|
227
|
+
| **Cache** | Redis/memory caching, TTL helpers | [docs/cache.md](docs/cache.md) |
|
|
228
|
+
| **Storage** | S3, local, memory file storage | [docs/storage.md](docs/storage.md) |
|
|
229
|
+
| **Observability** | Metrics, tracing, dashboards | [docs/observability.md](docs/observability.md) |
|
|
230
|
+
| **Security** | Password policy, headers, MFA | [docs/security.md](docs/security.md) |
|
|
231
|
+
| **Tenancy** | Multi-tenant isolation | [docs/tenancy.md](docs/tenancy.md) |
|
|
232
|
+
| **CLI** | Command-line tools | [docs/cli.md](docs/cli.md) |
|
|
233
|
+
|
|
234
|
+
## 🏃 Running the Example
|
|
235
|
+
|
|
236
|
+
See all features working together:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
git clone https://github.com/nfraxlab/svc-infra.git
|
|
240
|
+
cd svc-infra
|
|
241
|
+
|
|
242
|
+
# Setup and run
|
|
243
|
+
make setup-template # Creates DB, runs migrations
|
|
244
|
+
make run-template # Starts at http://localhost:8001
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Visit http://localhost:8001/docs to explore the API.
|
|
248
|
+
|
|
249
|
+
## 🤝 Related Packages
|
|
250
|
+
|
|
251
|
+
svc-infra is part of the **nfrax** infrastructure suite:
|
|
252
|
+
|
|
253
|
+
| Package | Purpose |
|
|
254
|
+
|---------|---------|
|
|
255
|
+
| **[svc-infra](https://github.com/nfraxlab/svc-infra)** | Backend infrastructure (auth, billing, jobs, webhooks) |
|
|
256
|
+
| **[ai-infra](https://github.com/nfraxlab/ai-infra)** | AI/LLM infrastructure (agents, tools, RAG, MCP) |
|
|
257
|
+
| **[fin-infra](https://github.com/nfraxlab/fin-infra)** | Financial infrastructure (banking, portfolio, insights) |
|
|
258
|
+
|
|
259
|
+
## 📄 License
|
|
260
|
+
|
|
261
|
+
MIT License - use it for anything.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
<div align="center">
|
|
266
|
+
|
|
267
|
+
**Built with ❤️ by [nfraxlab](https://github.com/nfraxlab)**
|
|
268
|
+
|
|
269
|
+
[⭐ Star us on GitHub](https://github.com/nfraxlab/svc-infra) · [📦 View on PyPI](https://pypi.org/project/svc-infra/)
|
|
270
|
+
|
|
271
|
+
</div>
|