This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: openfga-rebac-cycle-detection-depth-fencing

Deterministic Contextual Tuple Cycle Detection and Depth Fencing for OpenFGA ReBAC

ReBAC evaluations utilizing dynamic contextual tuples are vulnerable to graph cycle exploitation and unbounded recursive traversal loops that exhaust engine resources. Systems MUST enforce client-side directed acyclic graph (DAG) cycle detection and deterministic depth fencing before dispatching authorization checks to OpenFGA. This invariant guarantees sub-millisecond p99 authorization latencies and shields identity infrastructure from algorithmic complexity denial-of-service (DoS) attacks.

Prohibited Anti-Pattern: Unchecked Contextual Tuple Forwarding Allowing Circular Traversal Loops and Algorithmic ReBAC Denial of Service

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Deterministic Contextual Tuple Cycle Detection and Depth Fencing for OpenFGA ReBAC - ReBAC evaluations utilizing dynamic contextual tuples are vulnerable to graph cycle exploitation and unbounded recursive traversal loops that exhaust engine resources. Systems MUST enforce client-side directed acyclic graph (DAG) cycle detection and deterministic depth fencing before dispatching authorization checks to OpenFGA. This invariant guarantees sub-millisecond p99 authorization latencies and shields identity infrastructure from algorithmic complexity denial-of-service (DoS) attacks.
globs: src/auth/**/*.ts, src/security/**/*.ts, src/services/authz/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-rebac-cycle-detection-depth-fencing"
---

# Deterministic Contextual Tuple Cycle Detection and Depth Fencing for OpenFGA ReBAC

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unchecked Contextual Tuple Forwarding Allowing Circular Traversal Loops and Algorithmic ReBAC Denial of Service

## System Constraints
You are a Principal Security Architect specializing in Fine-Grained Authorization (FGA) and Relationship-Based Access Control (ReBAC). You mandate strict invariant enforcement for OpenFGA contextual tuples, including deterministic cycle detection, bounded graph expansion, contextual tuple volume limits, and strict sub-millisecond timeout fences.

## Strict Guidelines
- Engineers MUST ALWAYS validate that contextual tuples form a strict Directed Acyclic Graph (DAG) before forwarding them to the OpenFGA client.
- Engineers MUST NOT forward raw, unvalidated client-supplied contextual tuples directly into OpenFGA `check` or `expand` calls.
- Services MUST enforce an explicit contextual tuple cap (maximum 20 tuples by default) and reject requests exceeding this threshold with a 400 Bad Request error.
- Services MUST implement deterministic graph depth fencing by capping the maximum resolution chain of contextual tuples to a configured depth limit (e.g., maximum depth of 4).
- Components NEVER treat cycle detection failures or depth fence violations as recoverable fallback authorizations; all structural anomalies MUST result in immediate fail-closed denial (`allowed: false`).
- Engineers MUST configure explicit client-side check timeouts (max 50ms) to prevent thread pool exhaustion in case engine-side depth resolution degrades.

## Bad vs Good Implementations
### Contextual Tuple Cycle Detection and Depth Fencing Guardrail

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Passing contextual tuples directly from request context to the OpenFGA client without cycle checks, depth limits, or tuple count fencing invites algorithmic denial of service. Attackers can inject cyclic relationships (A is member of B, B is member of A) or deeply chained hierarchies that force the authorization engine into exponential evaluation branches, violating sub-millisecond SLAs.
```typescript
import { OpenFgaClient, type ClientCheckRequest, type ClientContextualTuple } from '@openfga/sdk';

const fgaClient = new OpenFgaClient({
  apiUrl: process.env.FGA_API_URL!,
  storeId: process.env.FGA_STORE_ID!,
});

// ANTI-PATTERN: Forwards user-supplied contextual tuples directly to OpenFGA.
// A cyclic tuple set (e.g., group:A -> group:B -> group:A) or deeply nested chain
// triggers engine-level recursion, spike latency to seconds, and leads to thread starvation DoS.
export async function authorizeUser(
  user: string,
  relation: string,
  object: string,
  dynamicTuples: ClientContextualTuple[]
): Promise<boolean> {
  const response = await fgaClient.check({
    user,
    relation,
    object,
    contextualTuples: dynamicTuples,
  });

  return response.allowed ?? false;
}
```

#### Production Standard (Correct)
> **Standard**: The production implementation strictly enforces client-side invariants: Kahn's topological sort confirms the contextual tuples form a Directed Acyclic Graph (DAG) before hitting OpenFGA; graph expansion depth is bounded to a maximum of 4; tuple count is capped at 20; and evaluation is guarded by a 50ms race timeout that deterministically fails closed (`false`).
```typescript
import { OpenFgaClient, type ClientCheckRequest, type ClientContextualTuple } from '@openfga/sdk';

const MAX_CONTEXTUAL_TUPLES = 20;
const MAX_EXPANSION_DEPTH = 4;
const CHECK_TIMEOUT_MS = 50;

export class AuthorizationSecurityError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'AuthorizationSecurityError';
  }
}

/**
 * Validates that contextual tuples are acyclic and within the maximum allowed depth limit.
 */
export function validateTupleAcyclicityAndDepth(
  tuples: ClientContextualTuple[],
  maxDepth: number = MAX_EXPANSION_DEPTH
): void {
  if (tuples.length > MAX_CONTEXTUAL_TUPLES) {
    throw new AuthorizationSecurityError(`Contextual tuple count exceeds security limit of ${MAX_CONTEXTUAL_TUPLES}`);
  }

  const adjacency = new Map<string, string[]>();
  const inDegree = new Map<string, number>();
  const allNodes = new Set<string>();

  for (const { user, object } of tuples) {
    if (user === object) {
      throw new AuthorizationSecurityError(`Self-referential contextual tuple detected: ${user} -> ${object}`);
    }
    if (!adjacency.has(user)) adjacency.set(user, []);
    adjacency.get(user)!.push(object);
    inDegree.set(object, (inDegree.get(object) ?? 0) + 1);
    allNodes.add(user);
    allNodes.add(object);
  }

  // Kahn's Algorithm for cycle detection and depth evaluation
  const queue: Array<{ node: string; depth: number }> = [];
  for (const node of allNodes) {
    if ((inDegree.get(node) ?? 0) === 0) {
      queue.push({ node, depth: 1 });
    }
  }

  let visitedCount = 0;
  while (queue.length > 0) {
    const { node, depth } = queue.shift()!;
    visitedCount++;

    if (depth > maxDepth) {
      throw new AuthorizationSecurityError(`Contextual tuple graph depth ${depth} exceeds maximum fence of ${maxDepth}`);
    }

    const neighbors = adjacency.get(node) ?? [];
    for (const neighbor of neighbors) {
      const currentInDegree = (inDegree.get(neighbor) ?? 1) - 1;
      inDegree.set(neighbor, currentInDegree);
      if (currentInDegree === 0) {
        queue.push({ node: neighbor, depth: depth + 1 });
      }
    }
  }

  if (visitedCount !== allNodes.size) {
    throw new AuthorizationSecurityError('Cycle detected in ReBAC contextual tuple set');
  }
}

export async function authorizeUserSecure(
  fgaClient: OpenFgaClient,
  user: string,
  relation: string,
  object: string,
  dynamicTuples: ClientContextualTuple[]
): Promise<boolean> {
  // Pre-condition: deterministic client-side DAG and depth fencing
  validateTupleAcyclicityAndDepth(dynamicTuples);

  const checkPayload: ClientCheckRequest = {
    user,
    relation,
    object,
    contextualTuples: dynamicTuples,
  };

  const checkPromise = fgaClient.check(checkPayload);
  const timeoutPromise = new Promise<never>((_, reject) =>
    setTimeout(() => reject(new Error('FGA check evaluation timed out')), CHECK_TIMEOUT_MS)
  );

  try {
    const response = await Promise.race([checkPromise, timeoutPromise]);
    return response.allowed ?? false;
  } catch (error) {
    // Fail closed on evaluation failure, timeout, or security violation
    return false;
  }
}
```

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 Contextual Tuple Cycle Detection and Depth Fencing for OpenFGA ReBAC

Deterministic Contextual Tuple Cycle Detection and Depth Fencing for OpenFGA ReBAC defines an industrial-grade behavioral standard for security engineering. ReBAC evaluations utilizing dynamic contextual tuples are vulnerable to graph cycle exploitation and unbounded recursive traversal loops that exhaust engine resources. Systems MUST enforce client-side directed acyclic graph (DAG) cycle detection and deterministic depth fencing before dispatching authorization checks to OpenFGA. This invariant guarantees sub-millisecond p99 authorization latencies and shields identity infrastructure from algorithmic complexity denial-of-service (DoS) attacks. 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: Unchecked Contextual Tuple Forwarding Allowing Circular Traversal Loops and Algorithmic ReBAC Denial of Service 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 DriftUnchecked Contextual Tuple Forwarding Allowing Circular Traversal Loops and Algorithmic ReBAC Denial of ServiceCritical
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 validate that contextual tuples form a strict Directed Acyclic Graph (DAG) before forwarding them to the OpenFGA client.

Engineers MUST ALWAYS validate that contextual tuples form a strict Directed Acyclic Graph (DAG) before forwarding them to the OpenFGA client.

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 forward raw, unvalidated client-supplied contextual tuples directly into OpenFGA `check` or `expand` calls.

Engineers MUST NOT forward raw, unvalidated client-supplied contextual tuples directly into OpenFGA `check` or `expand` calls.

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 enforce an explicit contextual tuple cap (maximum 20 tuples by default) and reject requests exceeding this threshold with a 400 Bad Request error.

Services MUST enforce an explicit contextual tuple cap (maximum 20 tuples by default) and reject requests exceeding this threshold with a 400 Bad Request error.

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 implement deterministic graph depth fencing by capping the maximum resolution chain of contextual tuples to a configured depth limit (e.g., maximum depth of 4).

Services MUST implement deterministic graph depth fencing by capping the maximum resolution chain of contextual tuples to a configured depth limit (e.g., maximum depth of 4).

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 treat cycle detection failures or depth fence violations as recoverable fallback authorizations

Components NEVER treat cycle detection failures or depth fence violations as recoverable fallback authorizations; all structural anomalies MUST result in immediate fail-closed denial (`allowed: false`).

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

Engineers MUST configure explicit client-side check timeouts (max 50ms) to prevent thread pool exhaustion in case engine-side depth resolution degrades.

Engineers MUST configure explicit client-side check timeouts (max 50ms) to prevent thread pool exhaustion in case engine-side depth resolution degrades.

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 Contextual Tuple Cycle Detection and Depth Fencing for OpenFGA ReBAC critical for AI coding assistants?

ReBAC evaluations utilizing dynamic contextual tuples are vulnerable to graph cycle exploitation and unbounded recursive traversal loops that exhaust engine resources. Systems MUST enforce client-side directed acyclic graph (DAG) cycle detection and deterministic depth fencing before dispatching authorization checks to OpenFGA. This invariant guarantees sub-millisecond p99 authorization latencies and shields identity infrastructure from algorithmic complexity denial-of-service (DoS) attacks. 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 (Unchecked Contextual Tuple Forwarding Allowing Circular Traversal Loops and Algorithmic ReBAC Denial of Service) 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