This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: openfga-rebac-contextual-cache-invalidation

Deterministic OpenFGA Contextual Tuple Evaluation and Real-Time Invalidation

Enforces deterministic cryptographic cache key hashing and real-time event-driven cache invalidation for OpenFGA ReBAC graph evaluations. Prevents stale authorization privilege retention and cache poisoning by strictly binding contextual tuple snapshots, quantized temporal attributes, and transactional write invalidations to graph check operations.

Prohibited Anti-Pattern: Static TTL Caching of ReBAC Graph Checks with Non-Deterministic Contextual Tuples and Unsynchronized Tuple Mutation

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Deterministic OpenFGA Contextual Tuple Evaluation and Real-Time Invalidation - Enforces deterministic cryptographic cache key hashing and real-time event-driven cache invalidation for OpenFGA ReBAC graph evaluations. Prevents stale authorization privilege retention and cache poisoning by strictly binding contextual tuple snapshots, quantized temporal attributes, and transactional write invalidations to graph check operations.
globs: src/auth/**/*.{ts,tsx}, src/services/auth/**/*.{ts,tsx}, src/lib/fga/**/*.{ts,tsx}, src/infrastructure/auth/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-rebac-contextual-cache-invalidation"
---

# Deterministic OpenFGA Contextual Tuple Evaluation and Real-Time Invalidation

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Static TTL Caching of ReBAC Graph Checks with Non-Deterministic Contextual Tuples and Unsynchronized Tuple Mutation

## System Constraints
You are a Principal Security Architect enforcing OpenFGA Relationship-Based Access Control (ReBAC) Context Invalidation invariants. You mandate that authorization checks must never serve stale relational grants due to out-of-sync caching. You enforce deterministic, canonical serialization of contextual tuples and context conditions, require bidirectional write-through/event-driven cache evictions on tuple mutations, and prohibit unquantized temporal attributes in authorization cache keys.

## Strict Guidelines
- Engineers MUST ALWAYS construct authorization cache keys using canonical, sorted, SHA-256 hashed representations of user, relation, object, contextualTuples, and context parameters.
- Engineers MUST NOT cache OpenFGA check evaluations with static long-lived TTLs without an active real-time invalidation bus (CDC, Redis Pub/Sub, or event bus) driven by write/delete tuple operations.
- Services MUST atomically emit invalidation signals for both direct and transitive graph dependencies when calling `writeTuples` or `deleteTuples`.
- Contextual attributes representing temporal constraints (e.g., current time, shift window) MUST be quantized to deterministic time-window buckets before cache key generation to prevent cache blowout and time-drift bypasses.
- Components NEVER bypass contextual tuple verification when performing bulk or batched authorization evaluations (`batchCheck`).

## Bad vs Good Implementations
### Naive Static Check Caching vs Deterministic Key Invalidation Engine

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The authorization decision is cached for 1 hour without including the contextual tuples or contextual payload in the cache key. A user changing IPs or an administrator invoking `revokeAccess` will still be granted access because the cache is not invalidated upon tuple deletion, causing a severe authorization bypass.
```typescript
import { OpenFgaClient } from '@openfga/sdk';
import { redis } from './redis';

export class AuthService {
  constructor(private fgaClient: OpenFgaClient) {}

  async canAccess(userId: string, relation: string, documentId: string, clientIp: string): Promise<boolean> {
    // ANTI-PATTERN: Contextual tuples and dynamic context omitted from cache key
    const cacheKey = `auth:${userId}:${relation}:${documentId}`;
    const cached = await redis.get(cacheKey);
    if (cached !== null) {
      return cached === 'true';
    }

    const { allowed } = await this.fgaClient.check({
      user: `user:${userId}`,
      relation,
      object: `document:${documentId}`,
      contextualTuples: [
        { user: `user:${userId}`, relation: 'viewer', object: `ip-range:${clientIp}` }
      ],
      context: { current_time: new Date().toISOString() }
    });

    // ANTI-PATTERN: Blind 1-hour TTL without invalidation on tuple revocation
    await redis.set(cacheKey, String(allowed), 'EX', 3600);
    return allowed ?? false;
  }

  async revokeAccess(userId: string, relation: string, documentId: string): Promise<void> {
    // ANTI-PATTERN: Tuple deleted from FGA but cache is not invalidated
    await this.fgaClient.write({
      deletes: [{ user: `user:${userId}`, relation, object: `document:${documentId}` }]
    });
  }
}
```

#### Production Standard (Correct)
> **Standard**: Constructs deterministic cache keys incorporating canonicalized contextual tuples and quantized temporal windows. On tuple mutations (writes/deletes), it automatically invalidates all associated cached decisions using object-scoped keys, preventing stale authorization retention.
```typescript
import { OpenFgaClient, ClientWriteRequest } from '@openfga/sdk';
import { createHash } from 'node:crypto';
import { redis } from './redis';

export interface CheckContext {
  clientIp: string;
  epochSeconds: number;
}

export class AuthService {
  private static readonly QUANTIZATION_WINDOW_SECONDS = 60;
  private static readonly CACHE_TTL_SECONDS = 300;

  constructor(private fgaClient: OpenFgaClient) {}

  private buildCacheKey(
    user: string,
    relation: string,
    object: string,
    contextualTuples: Array<{ user: string; relation: string; object: string }>,
    quantizedEpoch: number
  ): string {
    const sortedTuples = [...contextualTuples].sort((a, b) => 
      `${a.user}#${a.relation}@${a.object}`.localeCompare(`${b.user}#${b.relation}@${b.object}`)
    );
    
    const payload = JSON.stringify({
      u: user,
      r: relation,
      o: object,
      t: sortedTuples,
      w: quantizedEpoch
    });

    const hash = createHash('sha256').update(payload).digest('hex');
    return `fga:check:${object}:${relation}:${hash}`;
  }

  async canAccess(userId: string, relation: string, documentId: string, ctx: CheckContext): Promise<boolean> {
    const user = `user:${userId}`;
    const object = `document:${documentId}`;
    const quantizedEpoch = Math.floor(ctx.epochSeconds / AuthService.QUANTIZATION_WINDOW_SECONDS);

    const contextualTuples = [
      { user, relation: 'origin_network', object: `ip_range:${ctx.clientIp}` }
    ];

    const cacheKey = this.buildCacheKey(user, relation, object, contextualTuples, quantizedEpoch);
    const cached = await redis.get(cacheKey);
    if (cached !== null) {
      return cached === '1';
    }

    const { allowed } = await this.fgaClient.check({
      user,
      relation,
      object,
      contextualTuples,
      context: { window: quantizedEpoch }
    });

    const result = allowed ?? false;
    await redis.set(cacheKey, result ? '1' : '0', 'EX', AuthService.CACHE_TTL_SECONDS);
    return result;
  }

  async mutateTuples(mutation: ClientWriteRequest): Promise<void> {
    await this.fgaClient.write(mutation);

    // Invalidate affected object subtrees deterministically
    const affectedObjects = new Set<string>();
    mutation.writes?.forEach(t => affectedObjects.add(t.object));
    mutation.deletes?.forEach(t => affectedObjects.add(t.object));

    const pipeline = redis.pipeline();
    for (const obj of affectedObjects) {
      const keys = await redis.keys(`fga:check:${obj}:*`);
      if (keys.length > 0) {
        pipeline.del(...keys);
      }
    }
    await pipeline.exec();
  }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Deterministic OpenFGA Contextual Tuple Evaluation and Real-Time Invalidation

Deterministic OpenFGA Contextual Tuple Evaluation and Real-Time Invalidation defines an industrial-grade behavioral standard for security engineering. Enforces deterministic cryptographic cache key hashing and real-time event-driven cache invalidation for OpenFGA ReBAC graph evaluations. Prevents stale authorization privilege retention and cache poisoning by strictly binding contextual tuple snapshots, quantized temporal attributes, and transactional write invalidations to graph check operations. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Static TTL Caching of ReBAC Graph Checks with Non-Deterministic Contextual Tuples and Unsynchronized Tuple Mutation Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftStatic TTL Caching of ReBAC Graph Checks with Non-Deterministic Contextual Tuples and Unsynchronized Tuple MutationCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS construct authorization cache keys using canonical, sorted, SHA-256 hashed representations of user, relation, object, contextualTuples, and context parameters.

Engineers MUST ALWAYS construct authorization cache keys using canonical, sorted, SHA-256 hashed representations of user, relation, object, contextualTuples, and context parameters.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT cache OpenFGA check evaluations with static long-lived TTLs without an active real-time invalidation bus (CDC, Redis Pub/Sub, or event bus) driven by write/delete tuple operations.

Engineers MUST NOT cache OpenFGA check evaluations with static long-lived TTLs without an active real-time invalidation bus (CDC, Redis Pub/Sub, or event bus) driven by write/delete tuple operations.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Services MUST atomically emit invalidation signals for both direct and transitive graph dependencies when calling `writeTuples` or `deleteTuples`.

Services MUST atomically emit invalidation signals for both direct and transitive graph dependencies when calling `writeTuples` or `deleteTuples`.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Contextual attributes representing temporal constraints (e.g., current time, shift window) MUST be quantized to deterministic time-window buckets before cache key generation to prevent cache blowout and time-drift bypasses.

Contextual attributes representing temporal constraints (e.g., current time, shift window) MUST be quantized to deterministic time-window buckets before cache key generation to prevent cache blowout and time-drift bypasses.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components NEVER bypass contextual tuple verification when performing bulk or batched authorization evaluations (`batchCheck`).

Components NEVER bypass contextual tuple verification when performing bulk or batched authorization evaluations (`batchCheck`).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Deterministic OpenFGA Contextual Tuple Evaluation and Real-Time Invalidation critical for AI coding assistants?

Enforces deterministic cryptographic cache key hashing and real-time event-driven cache invalidation for OpenFGA ReBAC graph evaluations. Prevents stale authorization privilege retention and cache poisoning by strictly binding contextual tuple snapshots, quantized temporal attributes, and transactional write invalidations to graph check operations. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Static TTL Caching of ReBAC Graph Checks with Non-Deterministic Contextual Tuples and Unsynchronized Tuple Mutation) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Deterministic