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

OpenFGA Transactional Log-Driven ReBAC Cache Invalidation & Consistency Pipeline

Mandates that all distributed and local relationship-based access control (ReBAC) cache layers invalidate permissions strictly via transactional log streams (CDC/Outbox) using monotonically increasing sequence tokens. Prevents privilege escalation and stale authorization decisions by guaranteeing causal consistency and eliminating reliance on loose TTLs for privilege revocation.

Prohibited Anti-Pattern: Dual-Write Invalidation or Static TTLs on Cached ReBAC Permission Evaluations

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenFGA Transactional Log-Driven ReBAC Cache Invalidation & Consistency Pipeline - Mandates that all distributed and local relationship-based access control (ReBAC) cache layers invalidate permissions strictly via transactional log streams (CDC/Outbox) using monotonically increasing sequence tokens. Prevents privilege escalation and stale authorization decisions by guaranteeing causal consistency and eliminating reliance on loose TTLs for privilege revocation.
globs: src/**/auth/**/*.{ts,tsx}, src/**/authorization/**/*.{ts,tsx}, src/**/fga/**/*.{ts,tsx}, src/**/cache/**/*.{ts,tsx}, src/**/consumers/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-rebac-cdc-cache-invalidation-pipeline"
---

# OpenFGA Transactional Log-Driven ReBAC Cache Invalidation & Consistency Pipeline

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Dual-Write Invalidation or Static TTLs on Cached ReBAC Permission Evaluations

## System Constraints
You are a Principal Security Architect enforcing the OpenFGA Real-Time ReBAC Cache Invalidation Pipeline standard. In ReBAC architectures, checking permissions requires traversing deep relation graphs, driving teams to cache evaluations in distributed memory (e.g., Redis). Mandate that: (1) Cache invalidation MUST NEVER occur via fire-and-forget dual-writes within application request handlers; (2) Invalidation MUST be driven by a reliable Transactional Log / Change Data Capture (CDC) consumer processing OpenFGA tuple changes; (3) Invalidation events MUST enforce monotonic ordering tokens (e.g., Kafka offset or Raft log index) to prevent out-of-order race conditions; (4) Authorization systems MUST fail closed or bypass caches when consumer lag exceeds the Maximum Acceptable Stale Window (e.g., >200ms); and (5) Graph reachability cache keys MUST partition deterministically by object, relation, and user identifier.

## Strict Guidelines
- Engineers MUST ALWAYS consume transactional CDC streams (e.g., Debezium, Kafka log, Outbox pattern) to invalidate authorization caches, ensuring atomicity with persistent state.
- Engineers MUST NOT perform in-line dual-writes (e.g., updating database and directly attempting `redis.del()`) inside HTTP request handlers, as network partitions and transaction rollbacks yield desynchronized access grants.
- Code MUST reject or drop invalidation messages that possess an older monotonic sequence or transaction version than the currently registered entity version in cache metadata.
- Services MUST monitor CDC consumer replication lag and automatically bypass cached authorization checks (falling back to direct, authoritative OpenFGA evaluation) if lag exceeds the defined SLA threshold.
- Components NEVER store OpenFGA evaluation results with long-lived TTLs (>60s) unless backed by verified, real-time reactive cache invalidation hooks.
- Cache keys for ReBAC evaluations MUST follow deterministic canonical naming: `rebac:{tenant}:{object_type}:{object_id}#{relation}@{user_type}:{user_id}` and maintain reverse lookup sets for wildcard/transitive invalidation.

## Bad vs Good Implementations
### Dual-Write Invalidation with Unbounded TTL vs. CDC-Driven Monotonic Pipeline

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: This anti-pattern performs direct cache deletion in the application write path (dual-write hazard). If Redis is temporarily unreachable or the request crashes after the FGA write, revoked permissions linger for up to an hour (3600s TTL). Furthermore, concurrent writes can arrive out of order, overwriting a newer revocation with older cached data.
```typescript
import { OpenFgaClient } from '@openfga/sdk';
import { Redis } from 'ioredis';

const fga = new OpenFgaClient({ /* config */ });
const redis = new Redis();

export async function revokeAccess(userId: string, docId: string): Promise<void> {
  // Anti-pattern: Dual-write in request path
  await fga.write({
    deletes: [{ user: `user:${userId}`, relation: 'viewer', object: `document:${docId}` }]
  });

  // Flaw 1: Network failure here leaves revoked access cached until TTL expires
  // Flaw 2: Fails to invalidate parent group or transitive relation keys
  // Flaw 3: Race conditions if a concurrent grant access executes out of order
  await redis.del(`fga:check:user:${userId}:viewer:document:${docId}`);
}

export async function checkAccess(userId: string, docId: string): Promise<boolean> {
  const cacheKey = `fga:check:user:${userId}:viewer:document:${docId}`;
  const cached = await redis.get(cacheKey);
  if (cached !== null) return cached === 'true';

  const { allowed } = await fga.check({
    user: `user:${userId}`,
    relation: 'viewer',
    object: `document:${docId}`
  });

  // Storing with arbitrary static TTL without CDC consistency guarantees
  await redis.set(cacheKey, String(allowed), 'EX', 3600);
  return allowed;
}
```

#### Production Standard (Correct)
> **Standard**: This production-grade solution enforces cache invalidation strictly via transactional CDC logs. It enforces monotonic sequence ordering via Redis Lua scripting to prevent out-of-order race conditions, incorporates an automated circuit-breaker for CDC replication lag, and isolates authorization queries deterministically.
```typescript
import { OpenFgaClient } from '@openfga/sdk';
import { Redis } from 'ioredis';

interface TupleEventLog {
  sequenceId: bigint;
  timestamp: number;
  operation: 'WRITE' | 'DELETE';
  tuple: { user: string; relation: string; object: string };
}

export class RebacCacheInvalidationConsumer {
  private readonly MAX_LAG_MS = 250;

  constructor(private readonly redis: Redis, private readonly fga: OpenFgaClient) {}

  public async handleCdcTupleEvent(event: TupleEventLog): Promise<void> {
    const currentLag = Date.now() - event.timestamp;
    if (currentLag > this.MAX_LAG_MS) {
      // Mark tenant/object as degraded; subsequent checks will bypass cache
      await this.redis.set(`rebac:circuit:lag:${event.tuple.object}`, 'true', 'EX', 5);
    }

    const { user, relation, object } = event.tuple;
    const canonicalPrefix = `rebac:${object}#${relation}`;
    const versionKey = `rebac:ver:${object}`;

    // Invalidate atomically using Lua script ensuring monotonic sequence ordering
    const luaScript = `
      local currentVer = redis.call('GET', KEYS[1])
      if not currentVer or tonumber(ARGV[1]) > tonumber(currentVer) then
        redis.call('SET', KEYS[1], ARGV[1])
        local keys = redis.call('KEYS', ARGV[2])
        for _, k in ipairs(keys) do
          redis.call('DEL', k)
        end
        return 1
      end
      return 0
    `;

    await this.redis.eval(
      luaScript,
      1,
      versionKey,
      event.sequenceId.toString(),
      `${canonicalPrefix}*`
    );
  }

  public async checkAuthorization(user: string, relation: string, object: string): Promise<boolean> {
    const isLagging = await this.redis.exists(`rebac:circuit:lag:${object}`);
    const cacheKey = `rebac:${object}#${relation}@${user}`;

    if (!isLagging) {
      const cached = await this.redis.get(cacheKey);
      if (cached !== null) {
        return cached === '1';
      }
    }

    // Authoritative OpenFGA check
    const { allowed } = await this.fga.check({ user, relation, object });

    if (!isLagging) {
      // Short TTL as safety fallback; primary invalidation driven by CDC pipeline
      await this.redis.set(cacheKey, allowed ? '1' : '0', 'EX', 30);
    }

    return allowed;
  }
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: OpenFGA Transactional Log-Driven ReBAC Cache Invalidation & Consistency Pipeline

OpenFGA Transactional Log-Driven ReBAC Cache Invalidation & Consistency Pipeline defines an industrial-grade behavioral standard for security engineering. Mandates that all distributed and local relationship-based access control (ReBAC) cache layers invalidate permissions strictly via transactional log streams (CDC/Outbox) using monotonically increasing sequence tokens. Prevents privilege escalation and stale authorization decisions by guaranteeing causal consistency and eliminating reliance on loose TTLs for privilege revocation. 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: Dual-Write Invalidation or Static TTLs on Cached ReBAC Permission Evaluations 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 DriftDual-Write Invalidation or Static TTLs on Cached ReBAC Permission EvaluationsCritical
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 consume transactional CDC streams (e.g., Debezium, Kafka log, Outbox pattern) to invalidate authorization caches, ensuring atomicity with persistent state.

Engineers MUST ALWAYS consume transactional CDC streams (e.g., Debezium, Kafka log, Outbox pattern) to invalidate authorization caches, ensuring atomicity with persistent state.

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 perform in-line dual-writes (e.g., updating database and directly attempting `redis.del()`) inside HTTP request handlers, as network partitions and transaction rollbacks yield desynchronized access grants.

Engineers MUST NOT perform in-line dual-writes (e.g., updating database and directly attempting `redis.del()`) inside HTTP request handlers, as network partitions and transaction rollbacks yield desynchronized access grants.

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

Code MUST reject or drop invalidation messages that possess an older monotonic sequence or transaction version than the currently registered entity version in cache metadata.

Code MUST reject or drop invalidation messages that possess an older monotonic sequence or transaction version than the currently registered entity version in cache metadata.

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

Services MUST monitor CDC consumer replication lag and automatically bypass cached authorization checks (falling back to direct, authoritative OpenFGA evaluation) if lag exceeds the defined SLA threshold.

Services MUST monitor CDC consumer replication lag and automatically bypass cached authorization checks (falling back to direct, authoritative OpenFGA evaluation) if lag exceeds the defined SLA threshold.

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 store OpenFGA evaluation results with long-lived TTLs (>60s) unless backed by verified, real-time reactive cache invalidation hooks.

Components NEVER store OpenFGA evaluation results with long-lived TTLs (>60s) unless backed by verified, real-time reactive cache invalidation hooks.

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.
6

Cache keys for ReBAC evaluations MUST follow deterministic canonical naming

Cache keys for ReBAC evaluations MUST follow deterministic canonical naming: `rebac:{tenant}:{object_type}:{object_id}#{relation}@{user_type}:{user_id}` and maintain reverse lookup sets for wildcard/transitive invalidation.

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 OpenFGA Transactional Log-Driven ReBAC Cache Invalidation & Consistency Pipeline critical for AI coding assistants?

Mandates that all distributed and local relationship-based access control (ReBAC) cache layers invalidate permissions strictly via transactional log streams (CDC/Outbox) using monotonically increasing sequence tokens. Prevents privilege escalation and stale authorization decisions by guaranteeing causal consistency and eliminating reliance on loose TTLs for privilege revocation. 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 (Dual-Write Invalidation or Static TTLs on Cached ReBAC Permission Evaluations) 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

OpenFGA