Entitlement Digest and Permission-Scoped Sharing
The entitlement digest is a core security mechanism in the org-shared cache. It ensures that engineers with different permissions never share cache entries, even within the same organization and repository.
Use this page when
- You need to understand how the cache key prevents cross-permission data leakage in the org-shared cache.
- You are troubleshooting low hit rates caused by too many unique entitlement digests.
- You want to verify that engineers with different permissions are properly isolated in cache.
Primary audience
- Primary: AI Agents, Technical Engineers
- Secondary: Technical Leaders
What Is the Entitlement Digest
The entitlement digest is a stable cryptographic hash of an engineer's resolved permissions at request time. It becomes part of the cache key, so only requests with the same permission profile can hit the same cache entries.
Cache key structure:
org_id + codebase_identity + entitlement_digest + semantic_hash
Two engineers share a cache entry only when all four components match.
Why Not key_id
You might expect the cache key to include the API key identifier (key_id). It deliberately does not.
The problem with key_id
If cache keys included key_id, every engineer would have their own isolated cache — even when they have identical permissions and are asking the same questions. This defeats the purpose of org-shared caching.
Example with key_id (bad):
- Alice (key:
ak_alice) asks "how to add a migration" → cache miss → stored. - Bob (key:
ak_bob) asks the same thing → cache miss (different key_id) → stored again. - Same response stored twice. No sharing. Wasted cost.
The solution with entitlement_digest
With entitlement digest, Alice and Bob share cache entries because they have the same permissions:
- Alice (permissions:
[read:api, write:api, read:cli]) asks "how to add a migration" → cache miss → stored with digestsha256(read:api,write:api,read:cli). - Bob (permissions:
[read:api, write:api, read:cli]) asks the same thing → cache hit (same digest). - One entry, shared. Cost saved.
When key_id would matter
Key_id is still relevant for audit and rate limiting — but not for cache scoping. The event log records which key made the request. The cache layer only cares about permission equivalence.
How the Digest Is Computed
The entitlement digest is computed from the resolved permission set at request time:
- The gateway resolves the requesting engineer's effective permissions (role assignments, team memberships, repo access).
- The permission identifiers are collected into a sorted, deduplicated list.
- The list is serialized to a canonical string format.
- A SHA-256 hash is computed over the canonical string.
- The first 16 bytes of the hash form the entitlement digest.
Canonical format
permissions := sort(deduplicate([
"read:api",
"write:api",
"read:cli",
"admin:settings"
]))
canonical := join(permissions, ",")
// "admin:settings,read:api,read:cli,write:api"
digest := sha256(canonical)[0:16]
// "a3f8b2c1d4e5f6a7"
Properties
- Deterministic: Same permissions always produce the same digest.
- Stable: Adding or removing unrelated permissions changes the digest only for affected engineers.
- Collision-resistant: 128-bit truncated SHA-256 provides sufficient uniqueness for cache scoping.
- Irreversible: You cannot reconstruct the permission list from the digest.
Security Implications
Engineers with same permissions share cache
This is by design. If two engineers have identical permissions, they can access the same resources through normal API calls. Sharing cache entries between them does not expose additional information.
Different permissions get different entries
An engineer with admin:settings permission will never hit a cache entry created by an engineer without that permission. The digest differs, so the cache keys do not match.
Permission changes invalidate cache access
If an engineer's permissions change (role added or removed), their entitlement digest changes. They immediately stop hitting their old cache entries and start building a new cache under the new digest.
No cross-org sharing
The org_id prefix in the cache key ensures entries are never shared across organizations, regardless of permission similarity.
Example Scenarios
Two engineers, same team, same permissions
Alice: permissions = [read:api, write:api, read:console]
Bob: permissions = [read:api, write:api, read:console]
Alice's digest: "a3f8b2c1d4e5f6a7"
Bob's digest: "a3f8b2c1d4e5f6a7" (identical)
→ They share cache entries.
Same team, different roles
Alice (senior): permissions = [read:api, write:api, admin:api, read:console]
Carol (junior): permissions = [read:api, read:console]
Alice's digest: "b7e2f1a8c3d4e5f6"
Carol's digest: "d1a2b3c4e5f6a7b8" (different)
→ They do NOT share cache entries.
Cross-team with equivalent permissions
Dave (platform-team): permissions = [read:api, write:api]
Eve (backend-team): permissions = [read:api, write:api]
Dave's digest: "c4d5e6f7a8b9c0d1"
Eve's digest: "c4d5e6f7a8b9c0d1" (identical)
→ They share cache entries, even though they are on different teams.
Monitoring
Checking digest distribution
The console Cache → Diagnostics page shows:
- Number of unique entitlement digests in your org.
- Cache entries per digest (helps identify if one permission profile dominates).
- Engineers per digest (shows permission clustering).
Optimal distribution
- Few unique digests (2–5): Most engineers share cache effectively. Good for flat orgs.
- Many unique digests (20+): Cache is highly fragmented. Consider simplifying your permission model.
- One dominant digest (80%+ of engineers): Excellent cache sharing. The majority of your org benefits from every cache entry.
Configuration
The entitlement digest is automatic — you do not configure it directly. However, you influence it through:
- Permission model design: Fewer distinct permission sets → fewer digests → more sharing.
- Role assignments: Standardize roles across teams to maximize digest overlap.
- Team structure: Teams with identical repo access naturally share the same digest.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Low hit rate despite similar work | Too many unique digests | Audit permission model for unnecessary granularity |
| Cache hit from unexpected user | Same permissions by coincidence | Expected behavior — same permissions = same access rights |
| Cache stopped working after role change | Digest changed | Expected — new permissions = new cache namespace |
| Two engineers with "same role" have different digests | Hidden permission differences | Check for team-level or repo-level overrides that add extra permissions |
For AI systems
- Canonical terms: Keeptrusts, entitlement digest, permission-scoped sharing, cache key, org-shared cache, access control, SHA-256 digest.
- Cache key structure:
org_id + codebase_identity + entitlement_digest + semantic_hash. - Best next pages: Cache Routing Rules, Repository-Isolated vs Monorepo-Group, Configuring Monorepo Group Caching.
For engineers
- The entitlement digest is automatic — you do not configure it directly. It is computed from the sorted, deduplicated resolved permission set at request time.
- Troubleshooting low hit rates: check Cache → Diagnostics for unique digest count. Many digests (20+) means cache fragmentation.
- Fix fragmentation by standardizing roles across teams to maximize digest overlap.
- Permission changes immediately change the digest — the engineer stops hitting old entries and starts a new cache namespace.
org_idprefix guarantees no cross-org sharing regardless of permission similarity.
For leaders
- The entitlement digest is the core security guarantee: engineers with different permissions never share cache entries, even within the same org.
- Fewer distinct permission sets = fewer digests = more cache sharing = lower cost. Simplify your RBAC model for maximum cache efficiency.
- Cross-team sharing is intentional and safe — if two engineers on different teams have identical permissions, they have identical access rights, so sharing is appropriate.
- Monitor digest distribution: one dominant digest (80%+ of engineers) means excellent cache economics.
Next steps
- Cache Routing Rules — layer team-based isolation on top of permission scoping
- Repository-Isolated vs Monorepo-Group — the other cache key dimension
- Cache Hit Rates: What Good Looks Like — benchmarks and troubleshooting