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

OpenFGA Transitive Userset Graph Depth Traversal and Cycle Mitigation Standard

Enforces bounded recursion depth limits and deterministic cycle detection across transitive relational usersets in OpenFGA authorization checks. Mitigates stack exhaustion, exponential state explosion, and denial-of-service vectors caused by self-referential or deeply nested tuple-to-userset relations.

Prohibited Anti-Pattern: Unbounded Userset Traversal and Missing Graph Depth Guardrails

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenFGA Transitive Userset Graph Depth Traversal and Cycle Mitigation Standard - Enforces bounded recursion depth limits and deterministic cycle detection across transitive relational usersets in OpenFGA authorization checks. Mitigates stack exhaustion, exponential state explosion, and denial-of-service vectors caused by self-referential or deeply nested tuple-to-userset relations.
globs: src/**/auth/**/*.{ts,js,go,py}, src/**/fga/**/*.{ts,js,go,py}, src/**/authorization/**/*.{ts,js,go,py}, **/model.fga
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-transitive-userset-graph-depth-guardrail"
---

# OpenFGA Transitive Userset Graph Depth Traversal and Cycle Mitigation Standard

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unbounded Userset Traversal and Missing Graph Depth Guardrails

## System Constraints
You are a Principal Security Architect enforcing resilient Relation-Based Access Control (ReBAC) policies. You MUST enforce deterministic depth limits, cycle detection, and fail-closed timeout boundaries on all transitive userset evaluations and OpenFGA graph resolutions. Unbounded recursive checks and circular relationship models that can induce denial-of-service are strictly prohibited.

## Strict Guidelines
- Engineers MUST ALWAYS configure an explicit `maxResolutionDepth` boundary (never exceeding 25 traversals) when invoking OpenFGA checks or custom graph traversals.
- Engineers MUST NOT allow circular tuple assignments in relational models without active visited-node tracking and deterministic cycle-breaking mechanisms.
- Services MUST enforce strict context deadlines and timeout budgets (e.g., maximum 150ms) on all relational check queries to prevent thread pool starvation.
- Policy models SHOULD avoid deeply nested `tuple_to_userset` relations across multi-tenant boundaries without partition keys to prevent cross-tenant graph explosion.
- Components NEVER fall back to permissive allow-states if graph recursion limits or traversal timeouts are reached; evaluation MUST fail closed.

## Bad vs Good Implementations
### Bounded Graph Traversal with Cycle Detection vs Unbounded Recursion

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The check manually traverses hierarchical group memberships recursively without visited-node tracking (cycle detection), depth limits, or timeout contexts. A single circular relation (Group A contains Group B, Group B contains Group A) causes an infinite loop and crashes the evaluation thread, inducing denial-of-service.
```typescript
import { OpenFgaApi, CheckRequest } from '@openfga/sdk';

export class AuthorizationService {
  constructor(private readonly fgaClient: OpenFgaApi) {}

  // ANTI-PATTERN: Naive unbounded recursive expansion across group memberships
  // Vulnerable to circular group references (A -> B -> A) and stack overflow DoS
  async isMemberOfNestedGroup(userId: string, groupId: string): Promise<boolean> {
    const checkResponse = await this.fgaClient.check({
      tuple_key: {
        user: `user:${userId}`,
        relation: 'member',
        object: `group:${groupId}`
      }
    });

    if (checkResponse.allowed) {
      return true;
    }

    // Unbounded custom expansion attempting to resolve parent hierarchies manually
    const parents = await this.fetchParentGroups(groupId);
    for (const parentId of parents) {
      if (await this.isMemberOfNestedGroup(userId, parentId)) {
        return true;
      }
    }

    return false;
  }

  private async fetchParentGroups(groupId: string): Promise<string[]> {
    return []; // Resolves raw parent tuples without cycle detection
  }
}
```

#### Production Standard (Correct)
> **Standard**: Enforces deterministic recursion limits (`MAX_TRAVERSAL_DEPTH`), tracks visited nodes to mitigate cycle-based infinite loops, wraps resolution in a strict 200ms timeout budget via `AbortController`, and guarantees fail-closed semantics on errors or depth exhaustion.
```typescript
import { OpenFgaApi, ClientCheckRequest } from '@openfga/sdk';

export class AuthorizationService {
  private static readonly MAX_TRAVERSAL_DEPTH = 15;
  private static readonly CHECK_TIMEOUT_MS = 200;

  constructor(private readonly fgaClient: OpenFgaApi) {}

  // PRODUCTION FIX: Context timeouts, visited set cycle detection, and bounded depth
  async isMemberOfNestedGroup(
    userId: string,
    groupId: string,
    visited: Set<string> = new Set(),
    currentDepth = 0
  ): Promise<boolean> {
    // Guardrail 1: Enforce bounded recursion depth
    if (currentDepth > AuthorizationService.MAX_TRAVERSAL_DEPTH) {
      console.warn(`[Security] Max graph traversal depth exceeded for user:${userId} on group:${groupId}`);
      return false; // Fail closed
    }

    // Guardrail 2: Deterministic cycle detection
    const nodeKey = `group:${groupId}`;
    if (visited.has(nodeKey)) {
      console.warn(`[Security] Relational cycle detected at node ${nodeKey}`);
      return false; // Break cycle safely
    }
    visited.add(nodeKey);

    // Guardrail 3: Strict timeout boundary
    const abortController = new AbortController();
    const timeoutId = setTimeout(() => abortController.abort(), AuthorizationService.CHECK_TIMEOUT_MS);

    try {
      const checkPayload: ClientCheckRequest = {
        user: `user:${userId}`,
        relation: 'member',
        object: nodeKey
      };

      const checkResponse = await this.fgaClient.check(checkPayload, {
        signal: abortController.signal
      });

      if (checkResponse.allowed) {
        return true;
      }

      const parents = await this.fetchParentGroups(groupId);
      for (const parentId of parents) {
        const isAuthorized = await this.isMemberOfNestedGroup(
          userId,
          parentId,
          new Set(visited),
          currentDepth + 1
        );
        if (isAuthorized) return true;
      }

      return false;
    } catch (error) {
      // Fail-closed on timeout or traversal cancellation
      console.error(`[Security] Authorization evaluation failed closed: ${error}`);
      return false;
    } finally {
      clearTimeout(timeoutId);
    }
  }

  private async fetchParentGroups(groupId: string): Promise<string[]> {
    return [];
  }
}
```

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 Transitive Userset Graph Depth Traversal and Cycle Mitigation Standard

OpenFGA Transitive Userset Graph Depth Traversal and Cycle Mitigation Standard defines an industrial-grade behavioral standard for security engineering. Enforces bounded recursion depth limits and deterministic cycle detection across transitive relational usersets in OpenFGA authorization checks. Mitigates stack exhaustion, exponential state explosion, and denial-of-service vectors caused by self-referential or deeply nested tuple-to-userset relations. 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 Userset Traversal and Missing Graph Depth Guardrails 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 Userset Traversal and Missing Graph Depth GuardrailsCritical
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 configure an explicit `maxResolutionDepth` boundary (never exceeding 25 traversals) when invoking OpenFGA checks or custom graph traversals.

Engineers MUST ALWAYS configure an explicit `maxResolutionDepth` boundary (never exceeding 25 traversals) when invoking OpenFGA checks or custom graph traversals.

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 allow circular tuple assignments in relational models without active visited-node tracking and deterministic cycle-breaking mechanisms.

Engineers MUST NOT allow circular tuple assignments in relational models without active visited-node tracking and deterministic cycle-breaking mechanisms.

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 strict context deadlines and timeout budgets (e.g., maximum 150ms) on all relational check queries to prevent thread pool starvation.

Services MUST enforce strict context deadlines and timeout budgets (e.g., maximum 150ms) on all relational check queries to prevent thread pool starvation.

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

Policy models SHOULD avoid deeply nested `tuple_to_userset` relations across multi-tenant boundaries without partition keys to prevent cross-tenant graph explosion.

Policy models SHOULD avoid deeply nested `tuple_to_userset` relations across multi-tenant boundaries without partition keys to prevent cross-tenant graph explosion.

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 fall back to permissive allow-states if graph recursion limits or traversal timeouts are reached

Components NEVER fall back to permissive allow-states if graph recursion limits or traversal timeouts are reached; evaluation MUST fail closed.

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 Transitive Userset Graph Depth Traversal and Cycle Mitigation Standard critical for AI coding assistants?

Enforces bounded recursion depth limits and deterministic cycle detection across transitive relational usersets in OpenFGA authorization checks. Mitigates stack exhaustion, exponential state explosion, and denial-of-service vectors caused by self-referential or deeply nested tuple-to-userset relations. 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 Userset Traversal and Missing Graph Depth Guardrails) 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