Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/data-flow-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,14 @@ def custom_function():
ns:{namespace}:func:{module}.{qualname}:args:{blake2b_hash}
```

> **SDK convention, not a server contract.** The CachekitIO backend validates
> keys security-only (length cap, charset whitelist, `..` rejection,
> `ns:{namespace}:` prefix shape) and otherwise stores them as opaque strings —
> the `func:`/`args:` structure exists for deterministic generation and
> function-level invalidation inside this SDK. Other SDKs use shorter formats
> (TypeScript/Rust: `{ns}:{hash}`) against the same server. See
> `protocol/spec/cache-key-format.md` → Server-Side Requirements.

**Example:**
```python
@cache(namespace="users")
Expand Down
22 changes: 14 additions & 8 deletions src/cachekit/key_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ class CacheKeyGenerator:
"local": "l", # Reference caching (no serialization)
}

# Regex for chars allowed in the func component of a SaaS cache key.
# SaaS validates: /^[a-zA-Z0-9_.]{1,200}$/
# Regex for chars allowed in the func component of a cache key.
# The [a-zA-Z0-9_.]{1,200} shape is SDK convention (the SaaS validates
# security-only: charset whitelist [a-zA-Z0-9_.:-], `..` rejection,
# 400-char cap — see protocol/spec/cache-key-format.md). Sanitization is
# still required: qualnames like `<lambda>` carry chars outside the
# server's charset whitelist.
_FUNC_ALLOWED_RE = __import__("re").compile(r"[^A-Za-z0-9_.]")
_DOUBLE_DOT_RE = __import__("re").compile(r"\.{2,}")
_FUNC_NAME_MAX = 200
Expand Down Expand Up @@ -358,12 +362,14 @@ def _normalize_key(self, key: str) -> str:

@classmethod
def _sanitize_func_name(cls, module: str, qualname: str) -> str:
"""Sanitize module.qualname for SaaS cache-key compliance.

The SaaS ``func`` component must match ``[a-zA-Z0-9_.]{1,200}``
and must not contain ``..``. Nested functions have qualnames like
``outer.<locals>.inner`` and lambdas are ``<lambda>`` — the angle
brackets violate the regex.
"""Sanitize module.qualname for cache-key charset compliance.

The SaaS validates keys security-only (charset whitelist
``[a-zA-Z0-9_.:-]``, no ``..``, 400-char cap); the stricter
``[a-zA-Z0-9_.]{1,200}`` func shape kept here is SDK convention.
Nested functions have qualnames like ``outer.<locals>.inner`` and
lambdas are ``<lambda>`` — the angle brackets violate the server's
charset whitelist either way, so sanitization stays mandatory.

This replaces every disallowed char with ``_``, collapses runs of
``..`` into a single ``.``, and truncates to 200 chars. The mapping
Expand Down
Loading