identity-plan-kit 0.3.1__tar.gz → 0.3.2__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.
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/Makefile +25 -2
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/PKG-INFO +1 -1
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/pyproject.toml +2 -2
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/cache/plan_cache.py +87 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/services/plan_service.py +8 -4
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/plans/test_plan_cache_concurrent.py +105 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/uv.lock +1 -1
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/.gitignore +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/README.md +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/alembic/env.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/alembic/script.py.mako +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/alembic/versions/20250124_000000_initial_schema.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/alembic/versions/20250127_000000_add_password_hash.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/alembic.ini +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/integration/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/integration/fastapi_integration.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/integration/sample_alembic_env.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/integration/webhook_integration.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/playing/admin_usage.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/playing/basic_usage.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/playing/custom_error_formats.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/playing/extending_models.html +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/playing/extension_example.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/prod/.env.production.example +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/prod/Dockerfile +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/prod/docker-compose.yml +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/prod/nginx.conf +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/prod/production_setup.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/prod/prometheus.yml +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/README.md +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/config.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/locustfile.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/test_auth.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/test_database_stress.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/test_mixed_scenarios.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/test_plans_quota.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/test_quota_direct.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/test_rbac_cache.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/loadtests/utils.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/admin/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/admin/auth.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/admin/views.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dependencies.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/domain/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/domain/entities.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/domain/exceptions.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dto/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dto/requests.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dto/responses.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/handlers/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/handlers/oauth_routes.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/models/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/models/refresh_token.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/models/user.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/models/user_provider.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/repositories/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/repositories/token_repo.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/repositories/user_repo.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/services/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/services/auth_service.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/services/oauth_service.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/uow.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/cli.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/config.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/kit.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/migrations.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/cache/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/cache/user_plan_cache.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dependencies.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/domain/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/domain/entities.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/domain/exceptions.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dto/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dto/responses.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dto/usage.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/handlers/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/handlers/plan_routes.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/feature.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/feature_usage.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/plan.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/plan_limit.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/plan_permission.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/user_plan.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/repositories/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/repositories/plan_repo.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/repositories/usage_repo.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/services/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/uow.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/cache/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/cache/permission_cache.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/dependencies.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/domain/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/domain/entities.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/domain/exceptions.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/models/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/models/permission.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/models/role.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/models/role_permission.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/repositories/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/repositories/rbac_repo.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/services/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/services/rbac_service.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/uow.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/README.md +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/audit.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/circuit_breaker.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/cleanup_scheduler.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/database.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/error_formatter.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/exception_handlers.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/exceptions.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/graceful_shutdown.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/health.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/http_utils.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/lockout.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/logging.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/metrics.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/models.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/rate_limiter.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/request_id.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/schemas.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/security.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/state_store.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/uow.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/uuid7.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_auth_service.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_circuit_breaker.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_csrf_state.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_dependencies.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_domain_entities.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_http_utils.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_lockout.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_lockout_concurrent.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_oauth_service_resilience.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_security_comprehensive.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_token_security.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/conftest.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/conftest.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_concurrent_limit_merge.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_concurrent_plan_operations.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_concurrent_token_operations.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_concurrent_user_creation.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_concurrent_user_deactivation.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_limit_boundaries.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_plan_cache_race.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_quota_concurrency.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_token_cleanup.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_token_repository.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_usage_periods.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_user_repository.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/plans/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/plans/test_dependencies.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/plans/test_domain_entities.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/plans/test_period_edge_cases.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/plans/test_plan_service.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/rbac/__init__.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/rbac/test_permission_cache.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/rbac/test_permission_cache_concurrent.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/rbac/test_rbac_cache_stampede.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/rbac/test_rbac_service.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_audit_pii_masking.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_circuit_breaker_concurrent.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_cleanup_scheduler_concurrent.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_config_validation.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_exception_handlers.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_http_utils_security.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_rate_limiter.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_rate_limiter_concurrent.py +0 -0
- {identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_state_store_concurrent.py +0 -0
|
@@ -20,6 +20,9 @@ ENV_FILE ?= $(shell \
|
|
|
20
20
|
else echo ""; \
|
|
21
21
|
fi)
|
|
22
22
|
|
|
23
|
+
# PyPI config file (override with: make publish PYPIRC=path/to/.pypirc)
|
|
24
|
+
PYPIRC ?= $(HOME)/.pypirc
|
|
25
|
+
|
|
23
26
|
help: ## Show this help message
|
|
24
27
|
@echo "Usage: make [target]"
|
|
25
28
|
@echo ""
|
|
@@ -116,13 +119,33 @@ build-wheels: ## Build binary wheels for distribution
|
|
|
116
119
|
@echo "✓ Wheels built in dist/"
|
|
117
120
|
@ls -lh dist/*.whl
|
|
118
121
|
|
|
119
|
-
publish-test: build ## Publish package to TestPyPI
|
|
122
|
+
publish-test: build ## Publish package to TestPyPI (uses ~/.pypirc if present)
|
|
120
123
|
@echo "Publishing to TestPyPI..."
|
|
124
|
+
ifeq ($(wildcard $(PYPIRC)),)
|
|
121
125
|
$(UV) publish --index testpypi
|
|
126
|
+
else
|
|
127
|
+
@echo "Using credentials from $(PYPIRC)"
|
|
128
|
+
@TOKEN=$$(awk '/^\[testpypi\]/{found=1} found && /^password/{print $$3; exit}' $(PYPIRC)); \
|
|
129
|
+
if [ -n "$$TOKEN" ]; then \
|
|
130
|
+
$(UV) publish --index testpypi --token "$$TOKEN"; \
|
|
131
|
+
else \
|
|
132
|
+
$(UV) publish --index testpypi; \
|
|
133
|
+
fi
|
|
134
|
+
endif
|
|
122
135
|
|
|
123
|
-
publish: build ## Publish package to PyPI
|
|
136
|
+
publish: build ## Publish package to PyPI (uses ~/.pypirc if present)
|
|
124
137
|
@echo "Publishing to PyPI..."
|
|
138
|
+
ifeq ($(wildcard $(PYPIRC)),)
|
|
125
139
|
$(UV) publish
|
|
140
|
+
else
|
|
141
|
+
@echo "Using credentials from $(PYPIRC)"
|
|
142
|
+
@TOKEN=$$(awk '/^\[pypi\]/{found=1} found && /^password/{print $$3; exit}' $(PYPIRC)); \
|
|
143
|
+
if [ -n "$$TOKEN" ]; then \
|
|
144
|
+
$(UV) publish --token "$$TOKEN"; \
|
|
145
|
+
else \
|
|
146
|
+
$(UV) publish; \
|
|
147
|
+
fi
|
|
148
|
+
endif
|
|
126
149
|
|
|
127
150
|
ci: check test-cov ## Run all CI checks (lint, format, typecheck, tests with coverage)
|
|
128
151
|
@echo "✓ All CI checks passed!"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "identity-plan-kit"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = "Modern FastAPI library for authentication, RBAC, subscription plans, and usage tracking"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -140,7 +140,7 @@ testpaths = ["tests"]
|
|
|
140
140
|
addopts = "-v --tb=short"
|
|
141
141
|
|
|
142
142
|
[tool.bumpversion]
|
|
143
|
-
current_version = "0.3.
|
|
143
|
+
current_version = "0.3.2"
|
|
144
144
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
145
145
|
serialize = ["{major}.{minor}.{patch}"]
|
|
146
146
|
tag = true
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/cache/plan_cache.py
RENAMED
|
@@ -27,6 +27,20 @@ class PlanCacheEntry:
|
|
|
27
27
|
return datetime.now(UTC) > self.expires_at
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
@dataclass
|
|
31
|
+
class AllPlansCacheEntry:
|
|
32
|
+
"""Cache entry for the complete list of all plans."""
|
|
33
|
+
|
|
34
|
+
plans: list[Plan]
|
|
35
|
+
expires_at: datetime
|
|
36
|
+
fetched_at: float = field(default_factory=time.monotonic)
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def is_expired(self) -> bool:
|
|
40
|
+
"""Check if entry has expired."""
|
|
41
|
+
return datetime.now(UTC) > self.expires_at
|
|
42
|
+
|
|
43
|
+
|
|
30
44
|
class PlanCache:
|
|
31
45
|
"""
|
|
32
46
|
In-memory plan cache.
|
|
@@ -69,6 +83,8 @@ class PlanCache:
|
|
|
69
83
|
self._invalidated_at: dict[str, float] = {}
|
|
70
84
|
# Global invalidation timestamp for invalidate_all()
|
|
71
85
|
self._global_invalidated_at: float = 0.0
|
|
86
|
+
# Cache for the complete list of all plans
|
|
87
|
+
self._all_plans_cache: AllPlansCacheEntry | None = None
|
|
72
88
|
|
|
73
89
|
async def get(self, plan_code: str) -> Plan | None:
|
|
74
90
|
"""
|
|
@@ -174,12 +190,80 @@ class PlanCache:
|
|
|
174
190
|
self._cache[plan_code] = entry
|
|
175
191
|
return True
|
|
176
192
|
|
|
193
|
+
async def get_all(self) -> list[Plan] | None:
|
|
194
|
+
"""
|
|
195
|
+
Get cached list of all plans.
|
|
196
|
+
|
|
197
|
+
This operation is lock-free for better performance under high concurrency.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
List of all Plan entities or None if not cached/expired
|
|
201
|
+
"""
|
|
202
|
+
if not self._enabled:
|
|
203
|
+
return None
|
|
204
|
+
|
|
205
|
+
entry = self._all_plans_cache
|
|
206
|
+
if entry is None:
|
|
207
|
+
return None
|
|
208
|
+
|
|
209
|
+
if entry.is_expired:
|
|
210
|
+
return None
|
|
211
|
+
|
|
212
|
+
logger.debug("all_plans_cache_hit", count=len(entry.plans))
|
|
213
|
+
return entry.plans
|
|
214
|
+
|
|
215
|
+
async def set_all(
|
|
216
|
+
self,
|
|
217
|
+
plans: list[Plan],
|
|
218
|
+
fetched_at: float | None = None,
|
|
219
|
+
) -> bool:
|
|
220
|
+
"""
|
|
221
|
+
Cache the complete list of all plans.
|
|
222
|
+
|
|
223
|
+
Also populates individual plan entries for single-plan lookups.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
plans: List of all Plan entities to cache
|
|
227
|
+
fetched_at: Monotonic timestamp when plans were fetched from DB.
|
|
228
|
+
If provided, rejects stale writes after invalidation.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
True if cached, False if rejected as stale
|
|
232
|
+
"""
|
|
233
|
+
if not self._enabled:
|
|
234
|
+
return False
|
|
235
|
+
|
|
236
|
+
# Check for stale write if fetched_at is provided
|
|
237
|
+
if fetched_at is not None and fetched_at < self._global_invalidated_at:
|
|
238
|
+
logger.debug(
|
|
239
|
+
"all_plans_cache_stale_write_rejected",
|
|
240
|
+
reason="global_invalidation",
|
|
241
|
+
fetched_at=fetched_at,
|
|
242
|
+
invalidated_at=self._global_invalidated_at,
|
|
243
|
+
)
|
|
244
|
+
return False
|
|
245
|
+
|
|
246
|
+
# Cache the all-plans list
|
|
247
|
+
self._all_plans_cache = AllPlansCacheEntry(
|
|
248
|
+
plans=plans,
|
|
249
|
+
expires_at=datetime.now(UTC) + self._ttl,
|
|
250
|
+
fetched_at=fetched_at or time.monotonic(),
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
# Also populate individual plan entries
|
|
254
|
+
for plan in plans:
|
|
255
|
+
await self.set(plan.code, plan, fetched_at=fetched_at)
|
|
256
|
+
|
|
257
|
+
logger.debug("all_plans_cached", count=len(plans))
|
|
258
|
+
return True
|
|
259
|
+
|
|
177
260
|
async def invalidate(self, plan_code: str) -> None:
|
|
178
261
|
"""
|
|
179
262
|
Invalidate cached plan by code.
|
|
180
263
|
|
|
181
264
|
Records the invalidation timestamp to prevent stale writes from
|
|
182
265
|
concurrent requests that fetched data before invalidation.
|
|
266
|
+
Also invalidates the all-plans cache since it contains stale data.
|
|
183
267
|
|
|
184
268
|
Args:
|
|
185
269
|
plan_code: Plan code to invalidate
|
|
@@ -189,6 +273,8 @@ class PlanCache:
|
|
|
189
273
|
self._invalidated_at[plan_code] = time.monotonic()
|
|
190
274
|
# dict.pop() is atomic in Python
|
|
191
275
|
self._cache.pop(plan_code, None)
|
|
276
|
+
# Also invalidate the all-plans cache since it now contains stale data
|
|
277
|
+
self._all_plans_cache = None
|
|
192
278
|
logger.debug("plan_cache_invalidated", plan_code=plan_code)
|
|
193
279
|
|
|
194
280
|
async def invalidate_all(self) -> None:
|
|
@@ -202,6 +288,7 @@ class PlanCache:
|
|
|
202
288
|
# Record global invalidation timestamp BEFORE clearing
|
|
203
289
|
self._global_invalidated_at = time.monotonic()
|
|
204
290
|
self._cache.clear()
|
|
291
|
+
self._all_plans_cache = None
|
|
205
292
|
# Also clear key-specific invalidation timestamps to prevent memory growth
|
|
206
293
|
self._invalidated_at.clear()
|
|
207
294
|
logger.info("plan_cache_cleared")
|
|
@@ -1150,7 +1150,7 @@ class PlanService:
|
|
|
1150
1150
|
This is an optimized method that loads all plans with their
|
|
1151
1151
|
nested relationships in a minimal number of queries.
|
|
1152
1152
|
|
|
1153
|
-
Plans are cached
|
|
1153
|
+
Plans are cached as a complete list and individually for subsequent
|
|
1154
1154
|
single-plan lookups.
|
|
1155
1155
|
|
|
1156
1156
|
Args:
|
|
@@ -1159,15 +1159,19 @@ class PlanService:
|
|
|
1159
1159
|
Returns:
|
|
1160
1160
|
List of all Plan entities with permissions and limits
|
|
1161
1161
|
"""
|
|
1162
|
+
# Check cache first
|
|
1163
|
+
cached_plans = await self._plan_cache.get_all()
|
|
1164
|
+
if cached_plans is not None:
|
|
1165
|
+
return cached_plans
|
|
1166
|
+
|
|
1162
1167
|
# Get fetch timestamp BEFORE DB query for stale write prevention
|
|
1163
1168
|
fetch_ts = self._plan_cache.get_fetch_timestamp()
|
|
1164
1169
|
|
|
1165
1170
|
async with self._create_uow(session=session) as uow:
|
|
1166
1171
|
plans = await uow.plans.get_all_plans()
|
|
1167
1172
|
|
|
1168
|
-
# Cache
|
|
1169
|
-
|
|
1170
|
-
await self._plan_cache.set(plan.code, plan, fetched_at=fetch_ts)
|
|
1173
|
+
# Cache the complete list and individual plans
|
|
1174
|
+
await self._plan_cache.set_all(plans, fetched_at=fetch_ts)
|
|
1171
1175
|
|
|
1172
1176
|
logger.debug(
|
|
1173
1177
|
"all_plans_loaded",
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/plans/test_plan_cache_concurrent.py
RENAMED
|
@@ -585,3 +585,108 @@ class TestStaleWritePrevention:
|
|
|
585
585
|
result = await cache.set("pro", plan) # No fetched_at
|
|
586
586
|
assert result is True
|
|
587
587
|
assert await cache.get("pro") == plan
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
class TestAllPlansCache:
|
|
591
|
+
"""Tests for the all-plans cache (get_all/set_all)."""
|
|
592
|
+
|
|
593
|
+
async def test_get_all_returns_none_when_empty(self):
|
|
594
|
+
"""get_all returns None when cache is empty."""
|
|
595
|
+
cache = PlanCache(ttl_seconds=60)
|
|
596
|
+
result = await cache.get_all()
|
|
597
|
+
assert result is None
|
|
598
|
+
|
|
599
|
+
async def test_set_all_and_get_all(self):
|
|
600
|
+
"""set_all caches plans, get_all returns them."""
|
|
601
|
+
cache = PlanCache(ttl_seconds=60)
|
|
602
|
+
plans = [create_test_plan(f"plan_{i}") for i in range(3)]
|
|
603
|
+
|
|
604
|
+
result = await cache.set_all(plans)
|
|
605
|
+
assert result is True
|
|
606
|
+
|
|
607
|
+
cached = await cache.get_all()
|
|
608
|
+
assert cached is not None
|
|
609
|
+
assert len(cached) == 3
|
|
610
|
+
assert all(p.code in [f"plan_{i}" for i in range(3)] for p in cached)
|
|
611
|
+
|
|
612
|
+
async def test_set_all_populates_individual_cache(self):
|
|
613
|
+
"""set_all also populates individual plan cache entries."""
|
|
614
|
+
cache = PlanCache(ttl_seconds=60)
|
|
615
|
+
plans = [create_test_plan(f"plan_{i}") for i in range(3)]
|
|
616
|
+
|
|
617
|
+
await cache.set_all(plans)
|
|
618
|
+
|
|
619
|
+
# Individual plans should be cached
|
|
620
|
+
for i in range(3):
|
|
621
|
+
cached = await cache.get(f"plan_{i}")
|
|
622
|
+
assert cached is not None
|
|
623
|
+
assert cached.code == f"plan_{i}"
|
|
624
|
+
|
|
625
|
+
async def test_invalidate_clears_all_plans_cache(self):
|
|
626
|
+
"""Invalidating a single plan clears the all-plans cache."""
|
|
627
|
+
cache = PlanCache(ttl_seconds=60)
|
|
628
|
+
plans = [create_test_plan(f"plan_{i}") for i in range(3)]
|
|
629
|
+
|
|
630
|
+
await cache.set_all(plans)
|
|
631
|
+
assert await cache.get_all() is not None
|
|
632
|
+
|
|
633
|
+
# Invalidate a single plan
|
|
634
|
+
await cache.invalidate("plan_1")
|
|
635
|
+
|
|
636
|
+
# All-plans cache should be cleared
|
|
637
|
+
assert await cache.get_all() is None
|
|
638
|
+
|
|
639
|
+
# Other individual plans should still be cached
|
|
640
|
+
assert await cache.get("plan_0") is not None
|
|
641
|
+
assert await cache.get("plan_2") is not None
|
|
642
|
+
|
|
643
|
+
async def test_invalidate_all_clears_all_plans_cache(self):
|
|
644
|
+
"""invalidate_all clears the all-plans cache."""
|
|
645
|
+
cache = PlanCache(ttl_seconds=60)
|
|
646
|
+
plans = [create_test_plan(f"plan_{i}") for i in range(3)]
|
|
647
|
+
|
|
648
|
+
await cache.set_all(plans)
|
|
649
|
+
assert await cache.get_all() is not None
|
|
650
|
+
|
|
651
|
+
await cache.invalidate_all()
|
|
652
|
+
|
|
653
|
+
assert await cache.get_all() is None
|
|
654
|
+
|
|
655
|
+
async def test_all_plans_cache_expires(self):
|
|
656
|
+
"""All-plans cache respects TTL."""
|
|
657
|
+
cache = PlanCache(ttl_seconds=1)
|
|
658
|
+
plans = [create_test_plan(f"plan_{i}") for i in range(3)]
|
|
659
|
+
|
|
660
|
+
await cache.set_all(plans)
|
|
661
|
+
assert await cache.get_all() is not None
|
|
662
|
+
|
|
663
|
+
# Wait for expiration
|
|
664
|
+
await asyncio.sleep(1.1)
|
|
665
|
+
|
|
666
|
+
assert await cache.get_all() is None
|
|
667
|
+
|
|
668
|
+
async def test_set_all_stale_write_rejected(self):
|
|
669
|
+
"""set_all with stale fetch_ts is rejected after invalidate_all."""
|
|
670
|
+
cache = PlanCache(ttl_seconds=60)
|
|
671
|
+
plans = [create_test_plan(f"plan_{i}") for i in range(3)]
|
|
672
|
+
|
|
673
|
+
# Get fetch timestamp before invalidation
|
|
674
|
+
fetch_ts = cache.get_fetch_timestamp()
|
|
675
|
+
|
|
676
|
+
await asyncio.sleep(0.001)
|
|
677
|
+
await cache.invalidate_all()
|
|
678
|
+
|
|
679
|
+
# Stale write should be rejected
|
|
680
|
+
result = await cache.set_all(plans, fetched_at=fetch_ts)
|
|
681
|
+
assert result is False
|
|
682
|
+
assert await cache.get_all() is None
|
|
683
|
+
|
|
684
|
+
async def test_disabled_cache_returns_none(self):
|
|
685
|
+
"""Disabled cache (ttl=0) returns None for get_all."""
|
|
686
|
+
cache = PlanCache(ttl_seconds=0)
|
|
687
|
+
plans = [create_test_plan(f"plan_{i}") for i in range(3)]
|
|
688
|
+
|
|
689
|
+
result = await cache.set_all(plans)
|
|
690
|
+
assert result is False
|
|
691
|
+
|
|
692
|
+
assert await cache.get_all() is None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/integration/fastapi_integration.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/integration/sample_alembic_env.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/integration/webhook_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/examples/playing/custom_error_formats.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
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dependencies.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/domain/__init__.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/domain/entities.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/domain/exceptions.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dto/__init__.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dto/requests.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/dto/responses.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/handlers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/models/user.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/auth/services/__init__.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
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/cache/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dependencies.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/domain/__init__.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/domain/entities.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/domain/exceptions.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dto/__init__.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dto/responses.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/dto/usage.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/handlers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/__init__.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/feature.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/plan.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/plan_limit.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/models/user_plan.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/plans/services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/cache/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/dependencies.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/domain/__init__.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/domain/entities.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/domain/exceptions.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/models/__init__.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/models/permission.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/models/role.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/rbac/services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/circuit_breaker.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/database.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/error_formatter.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/http_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/rate_limiter.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/request_id.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/security.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/src/identity_plan_kit/shared/state_store.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
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_oauth_service_resilience.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/auth/test_security_comprehensive.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_concurrent_limit_merge.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_limit_boundaries.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_plan_cache_race.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_quota_concurrency.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_token_repository.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/integration/test_user_repository.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
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/rbac/test_permission_cache_concurrent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_circuit_breaker_concurrent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_http_utils_security.py
RENAMED
|
File without changes
|
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_rate_limiter_concurrent.py
RENAMED
|
File without changes
|
{identity_plan_kit-0.3.1 → identity_plan_kit-0.3.2}/tests/shared/test_state_store_concurrent.py
RENAMED
|
File without changes
|