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

OpenFGA Modular Schema Cycle-Termination and Recursion-Budget Guardrail

Enforces strict recursion-depth budgets, memoized graph evaluation checks, and acyclic invariant compilation on modular OpenFGA schemas and client-side graph traversals. Protects authorization engines against ReDoS-style denial-of-service vulnerabilities caused by self-referential relations, mutual group nestings, or trans-module tuple cycles. Guarantees deterministic evaluation bounds across distributed Zanzibar-like authorization deployments.

Prohibited Anti-Pattern: Unbounded Recursive Tuple Evaluation Inducing ReDoS and Resource Exhaustion in Modular OpenFGA Stores

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenFGA Modular Schema Cycle-Termination and Recursion-Budget Guardrail - Enforces strict recursion-depth budgets, memoized graph evaluation checks, and acyclic invariant compilation on modular OpenFGA schemas and client-side graph traversals. Protects authorization engines against ReDoS-style denial-of-service vulnerabilities caused by self-referential relations, mutual group nestings, or trans-module tuple cycles. Guarantees deterministic evaluation bounds across distributed Zanzibar-like authorization deployments.
globs: src/authz/**/*.ts, src/permissions/**/*.ts, src/fga/**/*.ts, **/*.fga, openfga.mod
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-cycle-termination-guardrail"
---

# OpenFGA Modular Schema Cycle-Termination and Recursion-Budget Guardrail

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unbounded Recursive Tuple Evaluation Inducing ReDoS and Resource Exhaustion in Modular OpenFGA Stores

## System Constraints
You are a Principal Security Architect enforcing zero-trust relationship-based access control (ReBAC) invariants using OpenFGA. You must eliminate unbounded recursion, cyclic resolution loops, and unmetered graph expansion in modular authorization models. Enforce static cycle detection in modular schemas and runtime recursion-budget limits on all Check/ListObjects operations.

## Strict Guidelines
- Engineers MUST ALWAYS configure OpenFGA clients with an explicit, bounded `max_concurrent_reads` and `max_checks_per_request` runtime budget to prevent graph-walking fan-out attacks.
- Engineers MUST NOT introduce trans-module cyclic relations (e.g., `folder:parent -> folder` coupled with `folder:viewer -> parent#viewer`) without static cycle-detection compilation checks via `@openfga/syntax-transformer` or the FGA CLI.
- Services MUST implement client-side memoized visited-path sets with depth-bounded contexts when simulating or pre-evaluating modular schema graphs in application middleware.
- Code SHOULD enforce deterministic time-to-live (TTL) and request timeouts on all batch `Check` operations to terminate degraded cyclic traversal branches.
- Components NEVER execute raw recursive relationship expansion without evaluating intermediate cycle markers (`Set<string>` node identifiers) in custom tuple-ingestion pipelines.

## Bad vs Good Implementations
### Unbounded Recursive Pre-Check Resolution vs. Bounded Memoized Resolution with Depth Guardrail

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The bad example recursively queries OpenFGA relations without maintaining a visited-set of nodes or establishing a recursion depth budget. In cyclic schemas (e.g., Folder A -> Folder B -> Folder A), this induces infinite traversal, thread starvation, and application-level ReDoS.
```typescript
import { OpenFgaClient } from '@openfga/sdk';

// ANTI-PATTERN: Recursive relation traversal without depth budget or cycle detection
export async function verifyNestedFolderAccess(
  fgaClient: OpenFgaClient,
  userId: string,
  folderId: string
): Promise<boolean> {
  // Recursively walks parent folders without visited set tracking
  const { allowed } = await fgaClient.check({
    user: `user:${userId}`,
    relation: 'can_view',
    object: `folder:${folderId}`,
  });

  if (allowed) return true;

  // Blind recursive parent lookup induces unbounded latency and cycles
  // if folder:parent points circularly back to an ancestor
  const relations = await fgaClient.read({
    object: `folder:${folderId}`,
    relation: 'parent',
  });

  for (const tuple of relations.tuples) {
    const parentFolderId = tuple.key.user.replace('folder:', '');
    const parentAllowed = await verifyNestedFolderAccess(fgaClient, userId, parentFolderId);
    if (parentAllowed) return true;
  }

  return false;
}
```

#### Production Standard (Correct)
> **Standard**: The good example imposes an immutable depth-budget counter and an in-memory visited set tracking traversed entities. Cyclic edges terminate immediately upon re-encountering a node, and exceeding the maximum recursion depth trips an explicit error, guaranteeing O(V + E) bounded execution time.
```typescript
import { OpenFgaClient, FgaError } from '@openfga/sdk';

interface TraversalContext {
  readonly maxDepth: number;
  readonly visited: ReadonlySet<string>;
}

const DEFAULT_MAX_DEPTH = 15;

// PRODUCTION FIX: Deterministic depth budget with cycle tracking and client isolation
export async function verifyNestedFolderAccess(
  fgaClient: OpenFgaClient,
  userId: string,
  folderId: string,
  context: TraversalContext = { maxDepth: DEFAULT_MAX_DEPTH, visited: new Set<string>() }
): Promise<boolean> {
  const currentTarget = `folder:${folderId}`;

  if (context.visited.has(currentTarget)) {
    // Cycle detected: safely prune path without unbounded recursion
    return false;
  }

  if (context.maxDepth <= 0) {
    throw new Error(`Authorization recursion budget exhausted at ${currentTarget}`);
  }

  const nextVisited = new Set(context.visited).add(currentTarget);
  const nextContext: TraversalContext = {
    maxDepth: context.maxDepth - 1,
    visited: nextVisited,
  };

  const { allowed } = await fgaClient.check({
    user: `user:${userId}`,
    relation: 'can_view',
    object: currentTarget,
  });

  if (allowed) return true;

  const { tuples } = await fgaClient.read({
    object: currentTarget,
    relation: 'parent',
  });

  for (const tuple of tuples) {
    const parentFolderId = tuple.key.user.replace('folder:', '');
    const parentAllowed = await verifyNestedFolderAccess(
      fgaClient,
      userId,
      parentFolderId,
      nextContext
    );
    if (parentAllowed) return true;
  }

  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 Modular Schema Cycle-Termination and Recursion-Budget Guardrail

OpenFGA Modular Schema Cycle-Termination and Recursion-Budget Guardrail defines an industrial-grade behavioral standard for security engineering. Enforces strict recursion-depth budgets, memoized graph evaluation checks, and acyclic invariant compilation on modular OpenFGA schemas and client-side graph traversals. Protects authorization engines against ReDoS-style denial-of-service vulnerabilities caused by self-referential relations, mutual group nestings, or trans-module tuple cycles. Guarantees deterministic evaluation bounds across distributed Zanzibar-like authorization deployments. 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 Tuple Evaluation Inducing ReDoS and Resource Exhaustion in Modular OpenFGA Stores 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 Tuple Evaluation Inducing ReDoS and Resource Exhaustion in Modular OpenFGA StoresCritical
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 OpenFGA clients with an explicit, bounded `max_concurrent_reads` and `max_checks_per_request` runtime budget to prevent graph-walking fan-out attacks.

Engineers MUST ALWAYS configure OpenFGA clients with an explicit, bounded `max_concurrent_reads` and `max_checks_per_request` runtime budget to prevent graph-walking fan-out attacks.

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 introduce trans-module cyclic relations (e.g., `folder

Engineers MUST NOT introduce trans-module cyclic relations (e.g., `folder:parent -> folder` coupled with `folder:viewer -> parent#viewer`) without static cycle-detection compilation checks via `@openfga/syntax-transformer` or the FGA CLI.

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 implement client-side memoized visited-path sets with depth-bounded contexts when simulating or pre-evaluating modular schema graphs in application middleware.

Services MUST implement client-side memoized visited-path sets with depth-bounded contexts when simulating or pre-evaluating modular schema graphs in application middleware.

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

Code SHOULD enforce deterministic time-to-live (TTL) and request timeouts on all batch `Check` operations to terminate degraded cyclic traversal branches.

Code SHOULD enforce deterministic time-to-live (TTL) and request timeouts on all batch `Check` operations to terminate degraded cyclic traversal branches.

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 execute raw recursive relationship expansion without evaluating intermediate cycle markers (`Set<string>` node identifiers) in custom tuple-ingestion pipelines.

Components NEVER execute raw recursive relationship expansion without evaluating intermediate cycle markers (`Set<string>` node identifiers) in custom tuple-ingestion pipelines.

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 Modular Schema Cycle-Termination and Recursion-Budget Guardrail critical for AI coding assistants?

Enforces strict recursion-depth budgets, memoized graph evaluation checks, and acyclic invariant compilation on modular OpenFGA schemas and client-side graph traversals. Protects authorization engines against ReDoS-style denial-of-service vulnerabilities caused by self-referential relations, mutual group nestings, or trans-module tuple cycles. Guarantees deterministic evaluation bounds across distributed Zanzibar-like authorization deployments. 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 Tuple Evaluation Inducing ReDoS and Resource Exhaustion in Modular OpenFGA Stores) 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