Skip to content

Encryption forbids the 'auto' serializer regardless of backend — local single-SDK FileBackend has no cross-SDK reader to protect #185

Description

@27Bslash6

Summary

CacheHandler rejects any non-cross-SDK serializer (notably auto) whenever encryption=True, gated purely on the encryption flag with no consideration of the backend. For a local, single-language FileBackend — read only by the Python SDK — the cross-SDK-interop rationale does not apply, yet auto + encryption is still a hard ConfigurationError. This conflates encrypted with cross-SDK-shared.

Where (source v0.9.0, installed 0.9.1)

src/cachekit/cache_handler.py:

# line 33
CROSS_SDK_SERIALIZER_NAMES = ("default", "std", "standard", "orjson", "arrow")

# line 348 — the guard's only enclosing condition is the encryption flag; no backend check
if self.encryption:
    ...
    if isinstance(serializer_name, str):
        if serializer_name not in CROSS_SDK_SERIALIZER_NAMES:
            raise ConfigurationError(
                "Encryption requires a cross-SDK-compatible serializer for cross-language "
                "interop, got serializer='...'. ... The 'auto' serializer emits "
                "Python-specific types that other SDKs cannot decode, so it cannot be used with encryption."
            )
    elif not getattr(type(serializer_name), "cross_sdk_compatible", False):
        raise ConfigurationError(...)

Why this is over-coupled

Serialization and encryption are already orthogonal in the implementation: EncryptionWrapper is a Decorator that composes any SerializerProtocol with the AES-256-GCM layer and threads the user's serializer through (it is not silently replaced, post-#134). So nothing technical forces encryption to constrain the serializer — the only coupling is this policy guard.

The guard's justification — "so the encrypted bytes remain decodable by other-language SDKs" — holds only when another-language SDK actually reads the cache. That is a property of the backend (SaaS CachekitIO / any shared store), not of encryption. A local FileBackend encrypted at rest and read solely by the Python process has no other-SDK reader, so requiring a cross-SDK wire format there buys nothing and costs auto's Python-type fidelity (sets, frozensets, datetime, UUID, Decimal, NumPy, pandas).

Impact

Anyone wanting an encrypted local cache that preserves rich Python types is forced onto std/orjson (JSON-ish types only), or must normalize/model_dump() every payload before the cache boundary. The only current escape is a custom serializer declaring cross_sdk_compatible=True — i.e. asserting a cross-SDK guarantee the cache does not actually need.

Proposed fix

Gate the cross-SDK serializer requirement on the backend's cross-SDK exposure, not on self.encryption:

  • SaaS / CachekitIO / any shared or cross-SDK backend → require a CROSS_SDK_SERIALIZER_NAMES serializer (current behavior).
  • Local single-SDK backend (FileBackend, in-process) → allow auto and other non-cross-SDK serializers with encryption; EncryptionWrapper still wraps the emitted bytes regardless.

Alternatively, an explicit opt-out (e.g. a backend capability flag / allow_local_serializer=True) for callers who know their encrypted cache is single-SDK.

Refs #134, which added this validation while wiring the user serializer through EncryptionWrapper.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    encryptionEncryption/cryptography relatedenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions