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

OpenFGA Graph Traversal Cycle and Depth Guardrails

Enforces strict bounded graph traversal, pre-write directed acyclic graph (DAG) cycle validation, and timeout-constrained contexts across OpenFGA authorization engines. Protects fine-grained authorization resolvers against algorithmic denial-of-service (DoS) and memory exhaustion caused by deeply nested or cyclical relationship tuples.

Prohibited Anti-Pattern: Unbounded Recursive ReBAC Traversal and Cyclic Tuple Persistence Inducing Algorithmic DoS

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenFGA Graph Traversal Cycle and Depth Guardrails - Enforces strict bounded graph traversal, pre-write directed acyclic graph (DAG) cycle validation, and timeout-constrained contexts across OpenFGA authorization engines. Protects fine-grained authorization resolvers against algorithmic denial-of-service (DoS) and memory exhaustion caused by deeply nested or cyclical relationship tuples.
globs: src/**/authz/**/*.{ts,tsx}, src/**/fga/**/*.{ts,tsx}, src/**/permissions/**/*.{ts,tsx}, src/**/security/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-graph-traversal-cycle-depth-guardrails"
---

# OpenFGA Graph Traversal Cycle and Depth Guardrails

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unbounded Recursive ReBAC Traversal and Cyclic Tuple Persistence Inducing Algorithmic DoS

## System Constraints
You are a Principal Security Architect enforcing OpenFGA graph traversal cycle and depth guardrails. ReBAC models (Relationship-Based Access Control) are vulnerable to algorithmic Denial-of-Service attacks through cyclical relationships (e.g., group A -> group B -> group A) and deep hierarchy chains. You must mandate pre-write acyclic validation, explicit traversal depth limits, strict context deadlines, and fail-closed error handling for all authorization queries.

## Strict Guidelines
- Engineers MUST ALWAYS validate relationship tuples against a DAG cycle detector prior to persisting hierarchical relations (e.g., `parent`, `member`, `child`) into OpenFGA.
- Engineers MUST NOT execute OpenFGA `check`, `expand`, or `listObjects` calls without an explicit timeout deadline (maximum 500ms for OLTP paths) and bounded resolution context.
- Code SHOULD enforce a maximum traversal depth budget (recommended <= 15 hops) in contextual tuple expansions and application-layer authorization resolvers.
- Services MUST intercept `ResolutionMaxDepthExceededException`, `FgaError`, and traversal timeout errors to fail closed (deny access) rather than throwing uncaught 500s or retrying blindly.
- Components NEVER allow client-supplied input to dynamically construct recursive relation chains without strict schema validation and cycle assertions before writing to the datastore.

## Bad vs Good Implementations
### Hierarchical Tuple Writing and Bounded Traversal Check

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Writing nested relations without verifying they form a DAG allows cyclical dependencies (group:A -> group:B -> group:A). Querying authorization without explicit timeout budgets or handling traversal limit errors can crash Node runtimes or stall API threads under cyclic or deeply nested graphs.
```typescript
import { OpenFgaClient } from '@openfga/sdk';

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

// ANTI-PATTERN: Blindly writing nested group/parent tuples without cycle detection,
// followed by unbounded resolution queries with no timeout or fail-closed handling.
export async function addGroupMember(groupId: string, memberGroupId: string) {
  await fga.writeTuples([{
    user: `group:${memberGroupId}`,
    relation: 'member',
    object: `group:${groupId}`,
  }]);
}

export async function checkAccess(userId: string, objectId: string): Promise<boolean> {
  // Vulnerable: No context timeout, unbounded resolution, fails open or crashes on cycle/depth limit
  const response = await fga.check({
    user: `user:${userId}`,
    relation: 'viewer',
    object: `document:${objectId}`,
  });
  return response.allowed ?? false;
}
```

#### Production Standard (Correct)
> **Standard**: Validates graph acyclicity before persisting tuples, sets an explicit AbortSignal timeout on all operations, restricts graph exploration to bounded depth, and catches traversal limit exceptions to fail closed (returning false).
```typescript
import { OpenFgaClient, FgaApiValidationError } from '@openfga/sdk';

const MAX_TRAVERSAL_DEPTH = 15;
const AUTHZ_TIMEOUT_MS = 350;

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

// Cyclic detection guard via DFS to verify the proposed edge does not create a cycle
async function assertAcyclic(
  source: string,
  target: string,
  relation: string,
  visited = new Set<string>(),
  depth = 0
): Promise<void> {
  if (depth > MAX_TRAVERSAL_DEPTH) {
    throw new Error(`Hierarchy exceeds maximum allowable depth of ${MAX_TRAVERSAL_DEPTH}`);
  }
  if (source === target || visited.has(source)) {
    throw new Error(`Cyclic graph relationship detected: ${source} -> ${target}`);
  }
  visited.add(source);

  // Check if target has a path back to source
  const { allowed } = await fga.check({
    user: target,
    relation: relation,
    object: source,
  }, { signal: AbortSignal.timeout(AUTHZ_TIMEOUT_MS) });

  if (allowed) {
    throw new Error(`Cycle detected: ${target} is already an ancestor of ${source}`);
  }
}

export async function addGroupMember(groupId: string, memberGroupId: string): Promise<void> {
  const source = `group:${groupId}`;
  const target = `group:${memberGroupId}`;

  // Enforce pre-write DAG invariant
  await assertAcyclic(source, target, 'member');

  await fga.write({
    writes: [{ user: target, relation: 'member', object: source }],
  }, { signal: AbortSignal.timeout(AUTHZ_TIMEOUT_MS) });
}

export async function checkAccess(userId: string, objectId: string): Promise<boolean> {
  try {
    const response = await fga.check({
      user: `user:${userId}`,
      relation: 'viewer',
      object: `document:${objectId}`,
    }, { signal: AbortSignal.timeout(AUTHZ_TIMEOUT_MS) });

    return Boolean(response.allowed);
  } catch (error) {
    // Fail closed on timeouts, recursion errors, or depth limit breaches
    console.error('Authorization resolution failed or timed out; failing closed.', { error, userId, objectId });
    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: OpenFGA Graph Traversal Cycle and Depth Guardrails

OpenFGA Graph Traversal Cycle and Depth Guardrails defines an industrial-grade behavioral standard for security engineering. Enforces strict bounded graph traversal, pre-write directed acyclic graph (DAG) cycle validation, and timeout-constrained contexts across OpenFGA authorization engines. Protects fine-grained authorization resolvers against algorithmic denial-of-service (DoS) and memory exhaustion caused by deeply nested or cyclical relationship tuples. 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: Unbounded Recursive ReBAC Traversal and Cyclic Tuple Persistence Inducing Algorithmic DoS 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 DriftUnbounded Recursive ReBAC Traversal and Cyclic Tuple Persistence Inducing Algorithmic DoSCritical
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 relationship tuples against a DAG cycle detector prior to persisting hierarchical relations (e.g., `parent`, `member`, `child`) into OpenFGA.

Engineers MUST ALWAYS validate relationship tuples against a DAG cycle detector prior to persisting hierarchical relations (e.g., `parent`, `member`, `child`) into OpenFGA.

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 execute OpenFGA `check`, `expand`, or `listObjects` calls without an explicit timeout deadline (maximum 500ms for OLTP paths) and bounded resolution context.

Engineers MUST NOT execute OpenFGA `check`, `expand`, or `listObjects` calls without an explicit timeout deadline (maximum 500ms for OLTP paths) and bounded resolution context.

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 SHOULD enforce a maximum traversal depth budget (recommended <= 15 hops) in contextual tuple expansions and application-layer authorization resolvers.

Code SHOULD enforce a maximum traversal depth budget (recommended <= 15 hops) in contextual tuple expansions and application-layer authorization resolvers.

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 intercept `ResolutionMaxDepthExceededException`, `FgaError`, and traversal timeout errors to fail closed (deny access) rather than throwing uncaught 500s or retrying blindly.

Services MUST intercept `ResolutionMaxDepthExceededException`, `FgaError`, and traversal timeout errors to fail closed (deny access) rather than throwing uncaught 500s or retrying blindly.

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 allow client-supplied input to dynamically construct recursive relation chains without strict schema validation and cycle assertions before writing to the datastore.

Components NEVER allow client-supplied input to dynamically construct recursive relation chains without strict schema validation and cycle assertions before writing to the datastore.

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 Graph Traversal Cycle and Depth Guardrails critical for AI coding assistants?

Enforces strict bounded graph traversal, pre-write directed acyclic graph (DAG) cycle validation, and timeout-constrained contexts across OpenFGA authorization engines. Protects fine-grained authorization resolvers against algorithmic denial-of-service (DoS) and memory exhaustion caused by deeply nested or cyclical relationship tuples. 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 (Unbounded Recursive ReBAC Traversal and Cyclic Tuple Persistence Inducing Algorithmic DoS) 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