Skip to content

Releases: SyntaxArc/ArchiPy

4.10.1

31 May 17:10

Choose a tag to compare

Fixed

Helpers - App Utils

  • FastAPI APM Middleware Ordering - Reordered FastAPI app setup so setup_metric_interceptor runs before
    setup_elastic_apm.
    • Elastic APM must be the outermost middleware to capture incoming FastAPI requests; the previous order placed the
      metrics interceptor outside APM, causing handler spans to be missed.

Adapters - Redis

  • Async Cluster Node Import - AsyncRedisAdapter._create_cluster_client now imports ClusterNode from
    redis.asyncio.cluster instead of the synchronous redis.cluster, matching the async cluster client's expected node
    type.

Changed

Adapters - Redis

  • Concrete Type Hints in Place of Generic Aliases - Replaced the generic RedisResponseType, RedisKeyType,
    RedisExpiryType, RedisAbsExpiryType, RedisIntegerResponseType, RedisListResponseType, RedisSetResponseType,
    RedisPatternType, and RedisSetType aliases with concrete return and parameter types across RedisAdapter,
    AsyncRedisAdapter, RedisPort, and AsyncRedisPort.
    • Cluster methods now declare specific shapes (e.g., cluster_info() -> dict[str, str] | None,
      cluster_slots() -> list[Any] | None, cluster_get_keys_in_slot(...) -> list[bytes | str] | None).
    • TTL and counter methods now return int directly (e.g., pttl, incrby).
    • Expiry parameters use int | timedelta and int | datetime for relative and absolute forms respectively.
    • Added from __future__ import annotations to archipy/adapters/redis/adapters.py and
      archipy/adapters/redis/ports.py and imported datetime / timedelta for the new typing.
    • RedisScoreCastType is retained; all other aliases are removed from archipy.adapters.redis.ports.

Adapters - Redis Mocks

  • Drop Removed Type Alias - AsyncRedisMock._create_async_wrapper now types the wrapped method as
    Callable[..., Awaitable[Any]] after RedisResponseType was removed from archipy.adapters.redis.ports.

Helpers - Rate Limit

  • Concrete Return Type for _check - FastAPIRestRateLimitHandler._check now returns int instead of the removed
    RedisResponseType alias and the TYPE_CHECKING import is dropped.

Tests

Tests - Keycloak

  • Audience Mapper for Token Introspection - Replaced the brittle realm-management:token-introspection role
    assignment in _step_create_client_and_update_adapter with a new _ensure_introspection_audience_mapper helper that
    installs an oidc-audience-mapper on freshly created clients.
    • Uses add_mapper_to_client / a_add_mapper_to_client to ensure the introspecting client appears in the access
      token aud claim, which Keycloak 26.6.2+ requires for successful introspection.
    • Re-initializes the admin adapter against the target realm before mutating the client and skips creation when a
      mapper with the same name already exists.

Chore

Test Containers

  • Image Bumps - Updated the test container images used by BDD scenarios in .env.test.
    • REDIS__IMAGE: redis:8.6.2-alpineredis:8.6.3-alpine
    • POSTGRES__IMAGE: postgres:18.3-alpinepostgres:18.4-alpine
    • KEYCLOAK__IMAGE: keycloak/keycloak:26.6.1keycloak/keycloak:26.6.2
    • KAFKA__IMAGE: apache/kafka:4.2.0apache/kafka:4.3.0

Dependencies

  • Runtime dependencies - Updated version pins for production dependencies.
    • requests: >=2.34.0>=2.34.2
    • jdatetime: >=5.2.0>=5.3.0
  • Optional extras - Updated optional adapter extras.
    • cache: cachetools>=7.1.1cachetools>=7.1.4
    • elastic-apm: elastic-apm>=6.25.0elastic-apm>=6.26.1
    • fastapi: fastapi[all]>=0.136.1fastapi[all]>=0.136.3
    • jwt: pyjwt>=2.12.1pyjwt>=2.13.0
    • keycloak: cachetools>=7.1.1cachetools>=7.1.4
    • minio: boto3>=1.43.6boto3>=1.43.14, cachetools>=7.1.1cachetools>=7.1.4
    • scylladb: cachetools>=7.1.1cachetools>=7.1.4
    • sqlalchemy / sqlalchemy-async: sqlalchemy>=2.0.49sqlalchemy>=2.0.50
    • starrocks: pymysql>=1.1.3pymysql>=1.2.0
  • Dev dependencies - Updated development tooling and typing stubs.
    • boto3-stubs: >=1.43.6>=1.43.14
    • ruff: >=0.15.12>=0.15.14
    • ty: >=0.0.35>=0.0.39
    • types-cachetools: >=7.0.0.20260503>=7.0.0.20260518
    • types-grpcio: >=1.0.0.20260508>=1.0.0.20260518
    • types-protobuf: >=7.34.1.20260508>=7.34.1.20260518
    • types-pymysql: >=1.1.0.20260508>=1.1.0.20260518
    • types-regex: >=2026.5.9.20260510>=2026.5.9.20260518
    • types-requests: >=2.33.0.20260513>=2.33.0.20260518

Full Changelog: 4.10.0...4.10.1

4.10.0

18 May 11:50

Choose a tag to compare

Added

Adapters - Keycloak

  • Batch UMA Permission Checks - Added check_permissions_batch to KeycloakPort and AsyncKeycloakPort (and their
    adapter implementations) for evaluating multiple (resource, scope) pairs in a single UMA call.
    • Returns a frozenset[tuple[str, str]] containing only the granted pairs from the requested set.
    • Sync implementation wraps KeycloakOpenID.uma_permissions; async implementation wraps a_uma_permissions.
    • Cached with ttl_cache_decorator(ttl_seconds=30, maxsize=200) (sync) and alru_cache(ttl=30, maxsize=200) (
      async) to avoid redundant Keycloak round-trips.
    • Existing check_permissions now documents check_permissions_batch as the preferred entry point when multiple
      pairs must be checked per request.

Changed

Adapters - Keycloak

  • get_userinfo Trusts UserInfo Endpoint - Removed the local validate_token precheck from both sync and async
    get_userinfo implementations.
    • The Keycloak UserInfo endpoint already validates the token server-side, so the extra local validation was
      redundant and an unnecessary network round-trip.
    • Dropped the now-unused InvalidTokenError import from archipy/adapters/keycloak/adapters.py.
    • Docstrings updated to call out that UserInfo handles validation.

Helpers - Keycloak Utils

  • Shared Adapter Instances - KeycloakUtils._get_keycloak_adapter and _get_async_keycloak_adapter now delegate to
    process-wide @cached factories (_shared_sync_adapter, _shared_async_adapter) instead of constructing a new
    adapter per decorator invocation.
  • Authorization Pipeline Consolidation - Extracted the gRPC auth-decorator authorization flow into reusable helpers
    and used the new batch permission API throughout.
    • Added _authorize_sync / _authorize_async helpers that validate the token, fetch token info, retrieve UserInfo,
      perform optional resource-ownership checks, enforce role requirements, and run batch permission checks.
    • Added _extract_roles, _check_resource_access, and _build_auth_context helpers to centralize role
      aggregation (realm + client), ownership/admin checks, and AuthContext construction.
    • Role enforcement now uses local set operations against UserInfo claims (issuperset / isdisjoint) rather than
      issuing separate has_all_roles / has_any_of_roles calls.
    • Permission enforcement uses check_permissions_batch and surfaces missing pairs via the missing_permissions
      field in PermissionDeniedError.additional_data.
    • BaseError instances raised inside async wrappers are re-raised after the optional gRPC abort, preventing them
      from being wrapped into InternalError.

Helpers - Decorators

  • Sharper Tracing Decorator Generics - capture_transaction, capture_span, async_capture_transaction, and
    async_capture_span now bind their generic F to local _Function / _AsyncFunction Protocol classes that
    require a __name__ attribute, replacing the looser Callable[..., Any] bound and giving callers better type
    narrowing on decorated functions.

Full Changelog: 4.9.3...4.10.0

4.9.3

13 May 13:52

Choose a tag to compare

Changed

Helpers - Rate Limit

  • Lazy Redis client initialization - The FastAPIRestRateLimitHandler now lazily initializes its Redis client to avoid import cycles and enable TYPE_CHECKING imports.
    • Added _create_redis_client() static method that imports AsyncRedisAdapter at call time with # noqa: PLC0415.
    • Changed from eager self.redis_client = AsyncRedisAdapter() in __init__ to lazy self._redis_client assignment.
    • Renamed redis_client to _redis_client to indicate private API.

Dependencies

  • Core dependencies - Updated version pins for several production dependencies.
    • pydantic: >=2.13.3>=2.13.4
    • pydantic-settings: >=2.14.0>=2.14.1
    • requests: >=2.33.1>=2.34.0
    • elasticsearch: >=9.3.0>=9.4.0
    • boto3 (minio group): >=1.43.2>=1.43.6
    • scylla-driver: >=3.29.9>=3.29.10
    • sentry-sdk: >=2.58.0>=2.60.0
  • Dev dependencies - Updated development and typing stubs.
    • boto3-stubs: >=1.43.2>=1.43.6
    • ty: >=0.0.34>=0.0.35
    • types-grpcio: >=1.0.0.20260408>=1.0.0.20260508
    • types-protobuf: >=7.34.1.20260503>=7.34.1.20260508
    • types-pymysql: >=1.1.0.20260408>=1.1.0.20260508
    • types-regex: >=2026.4.4.20260408>=2026.5.9.20260510
    • types-requests: >=2.33.0.20260503>=2.33.0.20260513
    • pymdown-extensions (docs group): >=10.21.2>=10.21.3

Tests

Test Configuration

  • Elasticsearch test container version - Updated ELASTIC__IMAGE from elastic/elasticsearch:9.4.0 to elastic/elasticsearch:9.4.1 in .env.test.

Full Changelog: 4.9.2...4.9.3

4.9.2

12 May 13:30

Choose a tag to compare

Changed

Configs - GrpcConfig

  • Thread worker count resolution - When THREAD_WORKER_COUNT is omitted, it is now assigned during model validation by the after-model resolve_thread_worker_count validator to THREAD_PER_CPU_CORE * (os.cpu_count() or 1).
    • Removed the unused resolved_thread_worker_count property.
    • gRPC server helpers now pass a concrete max_workers into ThreadPoolExecutor instead of None.
  • Default server and stub channel options - Refreshed SERVER_OPTIONS_CONFIG_LIST and STUB_OPTIONS_CONFIG_LIST defaults for clearer limits, keepalive alignment, and client resilience.
    • grpc.max_metadata_size default 16KB on both server and stub presets.
    • Server keepalive and HTTP/2 ping intervals aligned with client expectations to reduce ENHANCE_YOUR_CALM / GOAWAY issues; connection idle (10m) and max age (30m) with a short grace drain.
    • Stub keepalive at 5 minutes with a 20s timeout; grpc.service_config default timeout 10s, wait-for-ready, retry policy, and a retryThrottling block.

Fixed

Adapters - Saman Shaparak Payment

  • Missing TransactionDetail Handling - Fixed graceful handling of missing TransactionDetail in Saman payment adapters.
    • Changed from .get("TransactionDetail", {}) to .get("TransactionDetail") or {}
    • Prevents TypeError when API returns null instead of missing key

Full Changelog: 4.9.1...4.9.2

4.9.1

12 May 12:32

Choose a tag to compare

Fixed

Adapters - ScyllaDB

  • Async Callback Fix - Fixed async error handling in ScyllaDB adapter by replacing run_in_executor with callback-based approach.
    • Uses add_callbacks to bridge cassandra-driver's ResponseFuture to asyncio.Future
    • Avoids ThreadPoolExecutor bottleneck under high concurrency
    • Properly constructs ResultSet from raw rows in the success callback

Dependencies

Adapters - ScyllaDB

  • ScyllaDB and Driver Upgrades - Updated ScyllaDB test container and Python driver to latest versions.
    • Upgraded ScyllaDB Docker image to 2026.1.2
    • Updated scylla-driver to 3.29.10

Chore - Dependencies

  • Dependency Updates - Upgraded multiple Python packages for improved compatibility and security.
    • Updated idna to 3.14
    • Updated python-multipart to 0.0.28
    • Updated requests to 2.34.0

Helpers - Tracing

  • Elastic APM Initialization - Enhanced Elastic APM client initialization by excluding IS_ENABLED from model dump.
    • Prevents potential configuration leaks in APM agent initialization

Full Changelog: 4.9.0...4.9.1

4.9.0

09 May 16:43

Choose a tag to compare

Added

Adapters - Kafka

  • Null Commit and Batch Consume Support - Added support for null commits and batch consume operations in Kafka adapters.
    • Implemented batch consume capability for processing multiple messages in a single operation
    • Added null commit support for manual offset management scenarios
    • Comprehensive BDD test coverage for the new functionality

Full Changelog: 4.8.1...4.9.0

4.8.1

06 May 08:57

Choose a tag to compare

Changed

Helpers - Utils

  • Prometheus Utilities Refactor - Replaced standalone Prometheus helper functions with a PrometheusUtils class to centralize process lifecycle and server bootstrap operations.
    • Updated Prometheus server management call sites in AppUtils and BDD step implementations
    • Preserved existing behavior while improving maintainability and encapsulation

Adapters - ScyllaDB

  • CQL Identifier Validation - Tightened identifier sanitization in the ScyllaDB adapter to improve validation of dynamically built CQL statements.

Tests

Tests - Containers

  • Test Container Setup Updates - Refined test container fixtures for Elasticsearch and MinIO to align startup configuration with current dependency expectations.

Dependencies

Dependencies - Runtime and Tooling

  • Dependency Refresh - Updated core and transitive dependencies in pyproject.toml and uv.lock.
    • Upgraded boto3 and related AWS packages to 1.43.4
    • Upgraded cryptography to 48.0.0

Chore

Configs - Test Environment

  • Elasticsearch Test Image - Updated test environment defaults to Elasticsearch 9.4.0 for container-based integration tests.

4.8.0

03 May 12:50

Choose a tag to compare

Added

Helpers - Tracing

  • async_capture_transaction Decorator — New async-only transaction tracing decorator that enforces coroutine functions at decoration time, providing early failure detection for misuse.

    • Validates that decorated function is a coroutine using inspect.iscoroutinefunction
    • Raises TypeError immediately at import time if a sync function is passed
    • Mirrors the synchronous capture_transaction API with name and op parameters
  • async_capture_span Decorator — New async-only span tracing decorator for capturing child operations within async transactions.

    • Enforces coroutine functions at decoration time
    • Works with both Sentry and Elastic APM backends
    • Provides detailed performance insights for async operations
  • TracingUtils.outcome_for_exception Method — Added static method to determine the appropriate APM outcome string for exceptions.

    • Returns OUTCOME.SUCCESS for BaseError exceptions with HTTP status below 500 (client errors)
    • Returns OUTCOME.FAILURE for 5xx errors or unexpected exceptions
    • Enables accurate transaction outcome reporting in error handling paths

Configs - Sentry

  • SentryConfig.ENVIRONMENT Field — Added optional ENVIRONMENT field (str | None, default None) to explicitly set the Sentry environment name.

Changed

Configs - Base Config

  • Conditional Environment Assignment — Updated BaseConfig._post_init to only set ELASTIC_APM.ENVIRONMENT and SENTRY.ENVIRONMENT when they are None, preserving explicitly configured values.

Helpers - Tracing Utils

  • Initialization Tracking — Added _sentry_initialized and _elastic_apm_initialized class variables to prevent duplicate initialization attempts.
  • Lazy Initialization Enhancementinit_tracing_if_needed now checks initialization state before attempting to initialise each backend.

Helpers - gRPC Interceptors

  • Async gRPC Client Trace Interceptor — Changed from elasticapm.capture_span to elasticapm.async_capture_span for proper async span handling.
  • gRPC Server Trace Interceptor — Refactored to use elasticapm.set_transaction_outcome with OUTCOME constants instead of deprecated transaction.set_success() / transaction.set_failure() methods.
  • Async Servicer Context Wrapper — Added _AsyncServicerContextWrapper class to handle async gRPC server context, ensuring abort() is properly awaited in async servicer methods.

Helpers - App Utils

  • Interceptor Ordering Fix — Fixed AppUtils.create_async_grpc_app to add customized interceptors before creating the gRPC server, ensuring interceptors are properly registered.

Tests

Tests - Tracing

  • Async Decorator Tests — Added comprehensive BDD test scenarios for async_capture_transaction and async_capture_span decorators to verify proper transaction and span capture for async functions.

Full Changelog: 4.7.1...4.8.0

4.7.1

03 May 10:09

Choose a tag to compare

Added

Helpers - Tracing

  • TracingUtils Class - Introduced a new TracingUtils utility class in archipy/helpers/utils/tracing_utils.py to centralise all tracing initialisation and gRPC metadata helpers.
    • is_tracing_enabled(config) — checks whether any tracing backend (Sentry, Elastic APM, or OpenTelemetry) is active
    • init_tracing_if_needed(config) — lazily initialises the appropriate tracing backend once per process
    • grpc_status_indicates_success(status_code) — maps gRPC status codes to a boolean success/failure outcome
    • inject_outbound_metadata(metadata, carrier) — propagates W3C trace context into outbound gRPC metadata
    • extract_inbound_trace(metadata_dict) — extracts and activates an inbound trace context from gRPC metadata

Configs - Sentry

  • Extended SentryConfig - Added nine new optional fields to SentryConfig in ConfigTemplate for fine-grained Sentry SDK control.
    • SEND_DEFAULT_PII (bool, default False) — controls whether personally identifiable information (IP address, user) is sent
    • MAX_BREADCRUMBS (int, default 100) — limits the number of breadcrumbs stored per event
    • ATTACH_STACKTRACE (bool, default False) — attaches a stack trace to every captured message, not only exceptions
    • SERVER_NAME (str | None, default None) — overrides the hostname reported to Sentry
    • IN_APP_INCLUDE (list[str]) — module path prefixes that Sentry marks as in-app in stack traces
    • IN_APP_EXCLUDE (list[str]) — module path prefixes excluded from in-app marking
    • PROFILES_SAMPLE_RATE (float, default 0.0) — continuous profiling sample rate between 0.0 and 1.0
    • IGNORE_ERRORS (list[str]) — fully qualified or short exception type names that Sentry should silence
    • SHUTDOWN_TIMEOUT (int, default 2) — seconds the SDK waits to flush pending events on process exit
    • DEFAULT_INTEGRATIONS (bool, default True) — toggles Sentry's automatic default integrations

Changed

Helpers - Tracing

  • gRPC Client Interceptor Refactor - Rewrote archipy/helpers/interceptors/grpc/trace/client_interceptor.py to delegate tracing setup and metadata injection to TracingUtils, removing ~200 lines of inline logic.
  • gRPC Server Interceptor Refactor - Rewrote archipy/helpers/interceptors/grpc/trace/server_interceptor.py to use TracingUtils.extract_inbound_trace and TracingUtils.grpc_status_indicates_success for consistent span outcome reporting.
  • Tracing Decorator Refactor - Updated archipy/helpers/decorators/tracing.py to call TracingUtils.init_tracing_if_needed instead of duplicating Sentry and Elastic APM bootstrap logic inline.

Helpers - App Utils

  • Sentry Initialisation Delegated - AppUtils.init_sentry is now a no-op placeholder; Sentry initialisation is performed exclusively via TracingUtils inside create_fastapi_app, preventing double-initialisation.
  • Elastic APM Client Reuse - AppUtils.init_elastic_apm now calls elasticapm.get_client() first and only creates a new client when none exists, avoiding duplicate APM client instances.

Environment

  • .env.example Extended - Documented the ten new SENTRY_* environment variables introduced by the expanded SentryConfig.

Tests

Tests - Error Handling

  • Consolidated Error Handling Feature - Merged four separate BDD feature files (custom_errors.feature, error_utils.feature, fastapi_error_handling.feature, grpc_error_handling.feature) into a single error_handling.feature for easier maintenance and execution.
    • Removed features/custom_errors.feature, features/error_utils.feature, features/fastapi_error_handling.feature, and features/grpc_error_handling.feature
    • Removed matching step modules steps/custom_errors_steps.py, steps/error_utils_steps.py, steps/fastapi_error_handling_steps.py, and steps/grpc_error_handling_steps.py
    • Created unified features/error_handling.feature with all 238 scenario lines
    • Created unified features/steps/error_handling_steps.py consolidating all step definitions
  • Tagged Scenarios - Added descriptive tags to error handling scenarios for selective test execution.

Chore

  • Elasticsearch Test Image - Updated the Elasticsearch container image version in .env.test to align with CI test dependencies.

Full Changelog: 4.7.0...4.7.1

4.7.0

28 Apr 10:43

Choose a tag to compare

Added

Adapters - MinIO

  • MinIO Copy Object - Implemented copy_object method in MinioAdapter.
    • Supports copying objects within and between buckets
    • Added comprehensive BDD tests

Configuration

  • Advanced CORS Configuration - Added advanced CORS configuration options.
    • Extended ConfigTemplate with CORS-related settings
    • Added comprehensive BDD tests for CORS functionality

Changed

Environment

  • Example Environment - Updated .env.example with new CORS configuration variables.
    • Added CORS-related environment variable documentation

Tests - App Utils

  • Enhanced App Utils Tests - Added extensive BDD tests for advanced CORS configuration.
    • 89 new scenario steps added

Full Changelog: 4.6.0...4.7.0