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

OpenFGA ReBAC Tuple Consistency via Transactional CDC and Invalidation

Mandates that OpenFGA relationship tuple mutations and permission cache invalidations are strictly derived from transactional outbox events processed via Debezium Change Data Capture (CDC). Direct dual-writes to both the relational datastore and OpenFGA API are forbidden to prevent authorization split-brain and stale access control bypasses.

Prohibited Anti-Pattern: Dual-Writing Application State and OpenFGA Relationship Tuples Outside Transactional CDC

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenFGA ReBAC Tuple Consistency via Transactional CDC and Invalidation - Mandates that OpenFGA relationship tuple mutations and permission cache invalidations are strictly derived from transactional outbox events processed via Debezium Change Data Capture (CDC). Direct dual-writes to both the relational datastore and OpenFGA API are forbidden to prevent authorization split-brain and stale access control bypasses.
globs: src/**/*.ts, src/**/*.service.ts, src/auth/**/*.ts, src/modules/**/services/*.ts, src/infrastructure/cdc/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-rebac-cdc-consistency-guardrail"
---

# OpenFGA ReBAC Tuple Consistency via Transactional CDC and Invalidation

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Dual-Writing Application State and OpenFGA Relationship Tuples Outside Transactional CDC

## System Constraints
You are a Principal Security Architect enforcing ReBAC tuple consistency between primary application datastores and OpenFGA. Direct client dual-writes to OpenFGA alongside local database writes are strictly banned due to split-brain vulnerabilities. All tuple writes and L1/L2 authorization cache evictions must flow deterministically through a transactional outbox pattern driven by Debezium CDC with sequential log-sequence-number (LSN) ordering.

## Strict Guidelines
- Engineers MUST NEVER execute direct HTTP writes to OpenFGA (fgaClient.write) within inline business application service transactions.
- Engineers MUST ALWAYS persist authorization tuple state mutations to a dedicated transactional outbox table (e.g., `rebac_outbox`) inside the same ACID boundary as domain entity changes.
- CDC consumer pipelines MUST apply OpenFGA writes idempotently using deterministic contextual tuple keys (user, relation, object) and verify write acknowledgments before emitting cache invalidation events.
- Engineers MUST configure OpenFGA authorization checks to pass consistency tokens or enforce `HIGHER_CONSISTENCY` when evaluating permissions immediately following mutating requests to eliminate read-your-own-writes lag.
- Cache invalidation for permission checks MUST be derived strictly from the CDC commit stream, tagged with the underlying transactional LSN to prevent out-of-order resurrection of stale grants.
- Services MUST implement dead-letter queues (DLQ) with automated alert monitors for any failed CDC-to-OpenFGA tuple synchronization to detect authorization drift instantaneously.

## Bad vs Good Implementations
### Direct Dual-Write Anti-Pattern (Vulnerable to Split-Brain & Stale Eviction)

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Direct dual-writing to OpenFGA outside the primary transaction causes authorization divergence if the secondary write fails. Inverting the order causes phantom access if the DB transaction rolls back. Direct Redis deletion fails to prevent stale reads on replicas experiencing replication lag.
```typescript
import { OpenFgaClient } from '@openfga/sdk';
import { db } from '../infrastructure/db';
import { redis } from '../infrastructure/cache';

export async function assignProjectRole(userId: string, projectId: string, role: string) {
  // ANTI-PATTERN: Direct dual-write prone to network partition and split-brain
  await db.transaction(async (tx) => {
    await tx.projectMember.create({
      data: { userId, projectId, role },
    });
  });

  const fgaClient = new OpenFgaClient({ /* ... */ });
  
  // If this network call fails or server crashes here, the local DB has the grant
  // but OpenFGA does not, leaving authorization in an unrecoverable split-brain state.
  await fgaClient.write({
    writes: [{
      user: `user:${userId}`,
      relation: role,
      object: `project:${projectId}`,
    }],
  });

  // Cache eviction is racy and uncoordinated with replica lag
  await redis.del(`auth:check:${userId}:project:${projectId}`);
}
```

#### Production Standard (Correct)
> **Standard**: All authorization state transitions are bound to the primary transactional outbox. A dedicated Debezium CDC worker consumes the transaction log, guarantees delivery to OpenFGA, and executes a monotonic LSN-ordered cache invalidation to prevent stale authorization split-brains.
```typescript
import { OpenFgaClient, ClientWriteRequest } from '@openfga/sdk';
import { db } from '../infrastructure/db';
import { redis } from '../infrastructure/cache';

// 1. Application Layer: Writes exclusively to transactional outbox
export async function assignProjectRole(userId: string, projectId: string, role: string) {
  await db.transaction(async (tx) => {
    const membership = await tx.projectMember.create({
      data: { userId, projectId, role },
    });

    await tx.rebacOutbox.create({
      data: {
        aggregateType: 'PROJECT_MEMBERSHIP',
        aggregateId: membership.id,
        operation: 'INSERT',
        tupleUser: `user:${userId}`,
        tupleRelation: role,
        tupleObject: `project:${projectId}`,
        createdAt: new Date(),
      },
    });
  });
}

// 2. CDC Consumer Pipeline: Reads Debezium log, updates OpenFGA, atomically evicts cache
export async function handleDebeziumCdcEvent(event: {
  op: 'c' | 'd';
  after: { tupleUser: string; tupleRelation: string; tupleObject: string; id: string };
  source: { lsn: number; ts_ms: number };
}, fgaClient: OpenFgaClient) {
  const { tupleUser, tupleRelation, tupleObject } = event.after;
  const payload: ClientWriteRequest = event.op === 'c'
    ? { writes: [{ user: tupleUser, relation: tupleRelation, object: tupleObject }] }
    : { deletes: [{ user: tupleUser, relation: tupleRelation, object: tupleObject }] };

  // Synchronize ReBAC store with guaranteed at-least-once delivery
  await fgaClient.write(payload);

  // Deterministic cache bust with monotonic sequence check via Redis Lua script
  const cacheKey = `authz:${tupleUser}:${tupleObject}`;
  const lsnKey = `authz:lsn:${tupleUser}:${tupleObject}`;
  const luaBust = `
    local current_lsn = tonumber(redis.call('get', KEYS[2]) or '0')
    local new_lsn = tonumber(ARGV[1])
    if new_lsn >= current_lsn then
      redis.call('set', KEYS[2], new_lsn)
      return redis.call('del', KEYS[1])
    end
    return 0
  `;
  await redis.eval(luaBust, 2, cacheKey, lsnKey, event.source.lsn);
}
```

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: OpenFGA ReBAC Tuple Consistency via Transactional CDC and Invalidation

OpenFGA ReBAC Tuple Consistency via Transactional CDC and Invalidation defines an industrial-grade behavioral standard for security engineering. Mandates that OpenFGA relationship tuple mutations and permission cache invalidations are strictly derived from transactional outbox events processed via Debezium Change Data Capture (CDC). Direct dual-writes to both the relational datastore and OpenFGA API are forbidden to prevent authorization split-brain and stale access control bypasses. 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-Writing Application State and OpenFGA Relationship Tuples Outside Transactional CDC 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-Writing Application State and OpenFGA Relationship Tuples Outside Transactional CDCCritical
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 NEVER execute direct HTTP writes to OpenFGA (fgaClient.write) within inline business application service transactions.

Engineers MUST NEVER execute direct HTTP writes to OpenFGA (fgaClient.write) within inline business application service transactions.

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 ALWAYS persist authorization tuple state mutations to a dedicated transactional outbox table (e.g., `rebac_outbox`) inside the same ACID boundary as domain entity changes.

Engineers MUST ALWAYS persist authorization tuple state mutations to a dedicated transactional outbox table (e.g., `rebac_outbox`) inside the same ACID boundary as domain entity changes.

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

CDC consumer pipelines MUST apply OpenFGA writes idempotently using deterministic contextual tuple keys (user, relation, object) and verify write acknowledgments before emitting cache invalidation events.

CDC consumer pipelines MUST apply OpenFGA writes idempotently using deterministic contextual tuple keys (user, relation, object) and verify write acknowledgments before emitting cache invalidation events.

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

Engineers MUST configure OpenFGA authorization checks to pass consistency tokens or enforce `HIGHER_CONSISTENCY` when evaluating permissions immediately following mutating requests to eliminate read-your-own-writes lag.

Engineers MUST configure OpenFGA authorization checks to pass consistency tokens or enforce `HIGHER_CONSISTENCY` when evaluating permissions immediately following mutating requests to eliminate read-your-own-writes lag.

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

Cache invalidation for permission checks MUST be derived strictly from the CDC commit stream, tagged with the underlying transactional LSN to prevent out-of-order resurrection of stale grants.

Cache invalidation for permission checks MUST be derived strictly from the CDC commit stream, tagged with the underlying transactional LSN to prevent out-of-order resurrection of stale 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.
6

Services MUST implement dead-letter queues (DLQ) with automated alert monitors for any failed CDC-to-OpenFGA tuple synchronization to detect authorization drift instantaneously.

Services MUST implement dead-letter queues (DLQ) with automated alert monitors for any failed CDC-to-OpenFGA tuple synchronization to detect authorization drift instantaneously.

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 ReBAC Tuple Consistency via Transactional CDC and Invalidation critical for AI coding assistants?

Mandates that OpenFGA relationship tuple mutations and permission cache invalidations are strictly derived from transactional outbox events processed via Debezium Change Data Capture (CDC). Direct dual-writes to both the relational datastore and OpenFGA API are forbidden to prevent authorization split-brain and stale access control bypasses. 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-Writing Application State and OpenFGA Relationship Tuples Outside Transactional CDC) 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