Skip to content
Merged
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
2 changes: 1 addition & 1 deletion spec/cache-key-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ enforces is security-relevant (per `saas` issue #91 / SRP refactor):
| Traversal | `..` is rejected anywhere in the key, and so is a key of exactly `.`. |
| Namespace | A key starting `ns:` or `nsapi:` must be `{prefix}:{namespace}:{rest}`, with a namespace of 1–64 chars of `[a-zA-Z0-9_-]` and a non-empty `{rest}`; any other key with either prefix is rejected. Keys without either prefix scope to the `default` namespace. |
| Write spaces | `ns:` keys are mutable only by SDK (`ck_sdk_`) API keys; `nsapi:` keys only by direct (`ck_api_`) API keys. Reads are open to both. Legacy `ck_live_` keys predate the split and are exempt from it — they may write either class. No server-side retirement date is set for `ck_live_`. |
| Default namespace | Keys with neither prefix (TypeScript `{ns}:{hash}`, Rust caller-supplied keys, [Interop Mode](interop-mode.md) keys, bare hashes) are an **open** write space: any key class may write them, so the intra-tenant write-space isolation above does not protect them. Per-key namespace grants still apply — an API key restricted to named namespaces must include `default` to read or write unprefixed keys. |
| Default namespace | Keys with neither prefix (by default TypeScript `{ns}:{hash}`, Rust keys, [Interop Mode](interop-mode.md) keys, bare hashes) are an **open** write space: any key class may write them, so the intra-tenant write-space isolation above does not protect them. Per-key namespace grants still apply — an API key restricted to named namespaces must include `default` to read or write unprefixed keys. A TypeScript or Rust key that starts with `ns:` or `nsapi:`, as one under a TypeScript `wrap()` or Rust client namespace of `ns:team` does, is not in this open write space: the Namespace and Write spaces rows apply. |

Everything else in this document — segment count, `func:`/`args:` literals,
hash length, metadata flags — is SDK convention for deterministic key
Expand Down
2 changes: 1 addition & 1 deletion spec/saas-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ An SDK that serves a stale hit and owns revalidation (the recompute is the wrapp

This section is informative: it places no requirement on SDKs, and the [Remaining Freshness](#remaining-freshness) rules still govern an SDK's own local cache.

Every namespace has an edge budget: 5 seconds by default. A read answered by the CacheKit service may come from a copy held at the edge location that received it, but only if that copy was read from or written to the store within the budget, and only while the entry is fresh. So by default such a read reflects every write and delete that completed more than 5 seconds earlier, from any region, but not necessarily a more recent one, even one made through the same edge location. When two writes to the same key race, either value may be returned for up to the budget after the later write completes. Keys without an `ns:{name}:` or `nsapi:{name}:` prefix belong to the `default` namespace: cachekit-py's `namespace=` option writes `ns:{name}:` keys, while keys that cachekit-ts and cachekit-rs generate, whatever their namespace setting, and interop-mode keys from any SDK belong to `default`.
Every namespace has an edge budget: 5 seconds by default. A read answered by the CacheKit service may come from a copy held at the edge location that received it, but only if that copy was read from or written to the store within the budget, and only while the entry is fresh. So by default such a read reflects every write and delete that completed more than 5 seconds earlier, from any region, but not necessarily a more recent one, even one made through the same edge location. When two writes to the same key race, either value may be returned for up to the budget after the later write completes. Keys without an `ns:{name}:` or `nsapi:{name}:` prefix belong to the `default` namespace. cachekit-py's `namespace=` option writes `ns:{name}:` keys in auto mode, not with a decorator `key=` or in interop mode. Keys from cachekit-ts and cachekit-rs belong to `default` unless they start with `ns:` or `nsapi:`, as keys under a TypeScript `wrap()` or Rust client namespace of `ns:team` do ([namespace isolation decision](../decisions/namespace-isolation.md#context)). Interop-mode keys from any SDK always belong to `default`.

A budget of 0 sends every read to the store. A higher budget, up to 300 seconds, serves more reads from the nearest edge location, and such a read may return a value overwritten or deleted up to that many seconds earlier. An edge copy is never served past the TTL it was made under. Writes, deletes and TTL changes are not pushed between edge locations, so a `PATCH` of an entry's TTL reaches copies held at other locations only within the budget. A lowered budget usually applies within about 40 seconds, and within about 7 minutes under steady traffic; a request that reaches an edge location idle for a long time can still use the old budget for up to about 17 minutes, and reads keep the old budget's guarantee until the new one applies.

Expand Down
Loading