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

OpenFGA Transactional Outbox Dual-Write Reconciliation Boundary

Dual-writing directly to a domain database and the OpenFGA authorization tuple store introduces non-atomic failure modes, network partitions, and temporal race conditions that lead to privilege escalation or unauthorized data leaks. All OpenFGA relationship tuple mutations MUST be persisted transactionally into an outbox table within the primary business transaction and propagated asynchronously via an idempotent Change Data Capture (CDC) reconciliation consumer.

Prohibited Anti-Pattern: Non-Atomic Dual-Writing to Application DB and OpenFGA API During State Mutations

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenFGA Transactional Outbox Dual-Write Reconciliation Boundary - Dual-writing directly to a domain database and the OpenFGA authorization tuple store introduces non-atomic failure modes, network partitions, and temporal race conditions that lead to privilege escalation or unauthorized data leaks. All OpenFGA relationship tuple mutations MUST be persisted transactionally into an outbox table within the primary business transaction and propagated asynchronously via an idempotent Change Data Capture (CDC) reconciliation consumer.
globs: src/services/**/*.{ts,js}, src/modules/**/*.{ts,js}, src/repositories/**/*.{ts,js}, src/workers/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-transactional-outbox-reconciliation"
---

# OpenFGA Transactional Outbox Dual-Write Reconciliation Boundary

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Non-Atomic Dual-Writing to Application DB and OpenFGA API During State Mutations

## System Constraints
You are a Principal Security Architect enforcing the OpenFGA Transactional Outbox Dual-Write Reconciliation Boundary. Mandate that application code NEVER invokes OpenFGA write APIs (`writeTuples`, `write`, `delete`) inline within request lifecycles alongside domain database writes. All authorization tuple operations must be appended as outbox events inside the primary database ACID transaction to prevent out-of-order execution, partial failures, and privilege elevation vulnerabilities.

## Strict Guidelines
- Engineers MUST ALWAYS stage OpenFGA tuple modifications (`writes` and `deletes`) into an `outbox_events` table inside the exact same atomic database transaction as the primary domain entity mutation.
- Engineers MUST NOT execute direct API calls to OpenFGA (`fgaClient.write()`, `fgaClient.delete()`, or HTTP endpoints) inside web request handlers or domain services that modify database state.
- Services MUST ensure that outbox tuple mutation payloads include deterministic idempotency keys, entity sequence versions, and explicit tuple keys (`user`, `relation`, `object`).
- The CDC outbox processor MUST handle at-least-once delivery semantics by executing idempotent conditional writes against OpenFGA and verifying sequence numbers to eliminate out-of-order reconciliation races.
- Code SHOULD enforce fail-closed authorization fallbacks in ReBAC evaluation paths until the asynchronous outbox pipeline acknowledges tuple replication.

## Bad vs Good Implementations
### Dual-Write to DB and OpenFGA vs Transactional Outbox Pattern

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Directly invoking OpenFGA APIs outside the database transaction creates a dual-write race condition. If the service crashes or OpenFGA returns an error after the database commit, the database reflects the new owner while OpenFGA preserves the old owner's permissions, creating an authorization bypass or broken access control.
```typescript
import { OpenFgaClient } from '@openfga/sdk';
import { db } from '../db';
import { documents } from '../schema';

export async function transferDocumentOwnership(
  fgaClient: OpenFgaClient,
  documentId: string,
  previousOwnerId: string,
  newOwnerId: string
): Promise<void> {
  // ANTI-PATTERN: Direct dual-write leads to authorization state drift on partial failure.
  // If the DB commit succeeds but the OpenFGA write fails (or vice versa), state is desynchronized.
  await db.transaction(async (tx) => {
    await tx.update(documents)
      .set({ ownerId: newOwnerId })
      .where(eq(documents.id, documentId));
  });

  // Network failure or process crash here leaks permissions or grants unauthorized access
  await fgaClient.write({
    writes: [{ user: `user:${newOwnerId}`, relation: 'owner', object: `document:${documentId}` }],
    deletes: [{ user: `user:${previousOwnerId}`, relation: 'owner', object: `document:${documentId}` }]
  });
}
```

#### Production Standard (Correct)
> **Standard**: The domain mutation and the authorization tuple delta are bound within a single atomic database transaction. If the database transaction fails, neither change persists. If it succeeds, the outbox record is guaranteed to exist and will be delivered to OpenFGA by an at-least-once CDC reconciliation worker.
```typescript
import { db } from '../db';
import { documents, outboxEvents } from '../schema';
import { eq } from 'drizzle-orm';

export async function transferDocumentOwnership(
  documentId: string,
  previousOwnerId: string,
  newOwnerId: string,
  correlationId: string
): Promise<void> {
  // PRODUCTION STANDARD: Persist entity state and OpenFGA tuple mutations atomically.
  await db.transaction(async (tx) => {
    await tx.update(documents)
      .set({ ownerId: newOwnerId })
      .where(eq(documents.id, documentId));

    await tx.insert(outboxEvents).values({
      aggregateType: 'document',
      aggregateId: documentId,
      eventType: 'AUTHORIZATION_TUPLE_MUTATION',
      correlationId,
      payload: {
        writes: [
          { user: `user:${newOwnerId}`, relation: 'owner', object: `document:${documentId}` }
        ],
        deletes: [
          { user: `user:${previousOwnerId}`, relation: 'owner', object: `document:${documentId}` }
        ]
      },
      status: 'PENDING',
      createdAt: new Date()
    });
  });
  // The dedicated CDC worker consumes `outboxEvents` and reconciles OpenFGA tuples idempotently.
}
```

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 Transactional Outbox Dual-Write Reconciliation Boundary

OpenFGA Transactional Outbox Dual-Write Reconciliation Boundary defines an industrial-grade behavioral standard for security engineering. Dual-writing directly to a domain database and the OpenFGA authorization tuple store introduces non-atomic failure modes, network partitions, and temporal race conditions that lead to privilege escalation or unauthorized data leaks. All OpenFGA relationship tuple mutations MUST be persisted transactionally into an outbox table within the primary business transaction and propagated asynchronously via an idempotent Change Data Capture (CDC) reconciliation consumer. 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: Non-Atomic Dual-Writing to Application DB and OpenFGA API During State Mutations 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 DriftNon-Atomic Dual-Writing to Application DB and OpenFGA API During State MutationsCritical
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 stage OpenFGA tuple modifications (`writes` and `deletes`) into an `outbox_events` table inside the exact same atomic database transaction as the primary domain entity mutation.

Engineers MUST ALWAYS stage OpenFGA tuple modifications (`writes` and `deletes`) into an `outbox_events` table inside the exact same atomic database transaction as the primary domain entity mutation.

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 direct API calls to OpenFGA (`fgaClient.write()`, `fgaClient.delete()`, or HTTP endpoints) inside web request handlers or domain services that modify database state.

Engineers MUST NOT execute direct API calls to OpenFGA (`fgaClient.write()`, `fgaClient.delete()`, or HTTP endpoints) inside web request handlers or domain services that modify database state.

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 ensure that outbox tuple mutation payloads include deterministic idempotency keys, entity sequence versions, and explicit tuple keys (`user`, `relation`, `object`).

Services MUST ensure that outbox tuple mutation payloads include deterministic idempotency keys, entity sequence versions, and explicit tuple keys (`user`, `relation`, `object`).

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

The CDC outbox processor MUST handle at-least-once delivery semantics by executing idempotent conditional writes against OpenFGA and verifying sequence numbers to eliminate out-of-order reconciliation races.

The CDC outbox processor MUST handle at-least-once delivery semantics by executing idempotent conditional writes against OpenFGA and verifying sequence numbers to eliminate out-of-order reconciliation races.

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

Code SHOULD enforce fail-closed authorization fallbacks in ReBAC evaluation paths until the asynchronous outbox pipeline acknowledges tuple replication.

Code SHOULD enforce fail-closed authorization fallbacks in ReBAC evaluation paths until the asynchronous outbox pipeline acknowledges tuple replication.

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 Transactional Outbox Dual-Write Reconciliation Boundary critical for AI coding assistants?

Dual-writing directly to a domain database and the OpenFGA authorization tuple store introduces non-atomic failure modes, network partitions, and temporal race conditions that lead to privilege escalation or unauthorized data leaks. All OpenFGA relationship tuple mutations MUST be persisted transactionally into an outbox table within the primary business transaction and propagated asynchronously via an idempotent Change Data Capture (CDC) reconciliation consumer. 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 (Non-Atomic Dual-Writing to Application DB and OpenFGA API During State Mutations) 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