This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: openfga-temporal-expiration-cdc-consistency-standard

OpenFGA Temporal Tuple Expiration and CDC Stream Consistency Standard

Guarantees zero-lag authorization decisions by synchronizing short-lived contextual access grants with transactional Change Data Capture (CDC) invalidation events. Eliminates race conditions between transactional database state changes and OpenFGA authorization checks by enforcing transactional outbox patterns, context-driven condition validation, and idempotent stream reconciliation.

Prohibited Anti-Pattern: Asynchronous direct OpenFGA writes bypassing transactional boundaries or relying on background polling for tuple revocation

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenFGA Temporal Tuple Expiration and CDC Stream Consistency Standard - Guarantees zero-lag authorization decisions by synchronizing short-lived contextual access grants with transactional Change Data Capture (CDC) invalidation events. Eliminates race conditions between transactional database state changes and OpenFGA authorization checks by enforcing transactional outbox patterns, context-driven condition validation, and idempotent stream reconciliation.
globs: src/modules/authz/**/*.ts, src/infrastructure/events/**/*.ts, src/infrastructure/openfga/**/*.ts, src/domain/events/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openfga-temporal-expiration-cdc-consistency-standard"
---

# OpenFGA Temporal Tuple Expiration and CDC Stream Consistency Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Asynchronous direct OpenFGA writes bypassing transactional boundaries or relying on background polling for tuple revocation

## System Constraints
You are a Principal Engineer enforcing the OpenFGA Temporal Tuple Expiration and CDC Stream Consistency Standard. You must mandate strict transactional isolation when publishing relationship mutations, prevent direct uncoordinated API mutations to OpenFGA, and enforce deterministic temporal constraints using OpenFGA conditions and outbox-driven CDC consumers.

## Strict Guidelines
- Engineers MUST ALWAYS write relationship tuple mutations to a transactional outbox table within the exact same database transaction as the primary entity state modification.
- Engineers MUST NOT mutate OpenFGA relationship tuples synchronously in business request handlers prior to committing the primary database transaction.
- Engineers MUST enforce time-bound permissions using OpenFGA Conditions with evaluated ISO 8601 timestamps passed via contextual tuples at check-time, rather than relying on delayed cron sweeps for deletion.
- CDC consumer services MUST be idempotent, handling duplicate event deliveries via monotonic transaction log sequence numbers (e.g., LSN/Kafka offset tracking) before calling OpenFGA Write/Delete APIs.
- Authorization checks requiring strict read-after-write consistency MUST supply contextual tuples derived from the active session or uncommitted transaction state when CDC replication lag is detected.

## Bad vs Good Implementations
### Dual-Write Failure vs. Transactional Outbox with OpenFGA Conditional Temporal Evaluation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Direct dual-writing to OpenFGA outside the primary DB transaction introduces consistency divergence if the DB write succeeds but OpenFGA fails (or vice versa). Furthermore, using setTimeout for tuple expiration is fragile and non-fault-tolerant across service restarts, leading to permanently leaked privileges.
```typescript
import { OpenFgaClient } from '@openfga/sdk';
import { db } from '../infrastructure/db';

export async function grantTemporaryAccess(
  fgaClient: OpenFgaClient,
  userId: string,
  documentId: string,
  durationMs: number
): Promise<void> {
  // ANTI-PATTERN: Dual-write hazard. Database transaction and OpenFGA write are disconnected.
  // If the DB commit fails or server dies, the OpenFGA tuple remains active indefinitely.
  await db.transaction(async (trx) => {
    await trx('document_shares').insert({
      user_id: userId,
      document_id: documentId,
      expires_at: new Date(Date.now() + durationMs),
    });
  });

  // Non-transactional, non-conditional write susceptible to race conditions and orphan state
  await fgaClient.write({
    writes: [
      {
        user: `user:${userId}`,
        relation: 'editor',
        object: `document:${documentId}`,
      },
    ],
  });

  // Flawed revocation pattern: relying on setTimeout or background polling for temporal expiration
  setTimeout(async () => {
    await fgaClient.write({
      deletes: [
        {
          user: `user:${userId}`,
          relation: 'editor',
          object: `document:${documentId}`,
        },
      ],
    });
  }, durationMs);
}
```

#### Production Standard (Correct)
> **Standard**: Writes the access grant and an OpenFGA mutation task to an outbox within the exact same database transaction, eliminating dual-write divergence. Uses OpenFGA conditions with a dynamic timestamp context (`current_time` vs `expires_at`) to guarantee immediate privilege expiration at authorization check time, removing dependence on polling sweeps.
```typescript
import { OpenFgaClient } from '@openfga/sdk';
import { Knex } from 'knex';

interface OutboxEvent {
  id: string;
  aggregate_type: string;
  aggregate_id: string;
  event_type: 'RELATIONSHIP_CREATED' | 'RELATIONSHIP_REVOKED';
  payload: {
    user: string;
    relation: string;
    object: string;
    condition?: {
      name: string;
      context: Record<string, unknown>;
    };
  };
}

// Transactional Outbox Pattern: Ensures zero-drift between entity state and CDC stream
export async function grantTemporalAccessWithOutbox(
  trx: Knex.Transaction,
  userId: string,
  documentId: string,
  durationMs: number
): Promise<void> {
  const expiresAt = new Date(Date.now() + durationMs).toISOString();

  await trx('document_shares').insert({
    user_id: userId,
    document_id: documentId,
    expires_at: expiresAt,
  });

  // Outbox entry written in atomic transaction with primary business mutation
  await trx<OutboxEvent>('outbox_cdc_events').insert({
    id: crypto.randomUUID(),
    aggregate_type: 'document',
    aggregate_id: documentId,
    event_type: 'RELATIONSHIP_CREATED',
    payload: {
      user: `user:${userId}`,
      relation: 'editor',
      object: `document:${documentId}`,
      condition: {
        name: 'non_expired_grant',
        context: { expires_at: expiresAt },
      },
    },
  });
}

// CDC Stream Consumer: Synchronizes database events idempotently to OpenFGA
export async function handleCdcStreamEvent(
  fgaClient: OpenFgaClient,
  event: OutboxEvent
): Promise<void> {
  if (event.event_type === 'RELATIONSHIP_CREATED') {
    await fgaClient.write({
      writes: [
        {
          user: event.payload.user,
          relation: event.payload.relation,
          object: event.payload.object,
          condition: event.payload.condition,
        },
      ],
    });
  } else if (event.event_type === 'RELATIONSHIP_REVOKED') {
    await fgaClient.write({
      deletes: [
        {
          user: event.payload.user,
          relation: event.payload.relation,
          object: event.payload.object,
        },
      ],
    });
  }
}

// Check implementation: Evaluates temporal grant instantaneously without relying on CDC sweeps
export async function checkAccessWithTemporalContext(
  fgaClient: OpenFgaClient,
  userId: string,
  documentId: string
): Promise<boolean> {
  const response = await fgaClient.check({
    user: `user:${userId}`,
    relation: 'can_edit',
    object: `document:${documentId}`,
    context: {
      current_time: new Date().toISOString(),
    },
  });
  return Boolean(response.allowed);
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: OpenFGA Temporal Tuple Expiration and CDC Stream Consistency Standard

OpenFGA Temporal Tuple Expiration and CDC Stream Consistency Standard defines an industrial-grade behavioral standard for backend engineering. Guarantees zero-lag authorization decisions by synchronizing short-lived contextual access grants with transactional Change Data Capture (CDC) invalidation events. Eliminates race conditions between transactional database state changes and OpenFGA authorization checks by enforcing transactional outbox patterns, context-driven condition validation, and idempotent stream reconciliation. 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: Asynchronous direct OpenFGA writes bypassing transactional boundaries or relying on background polling for tuple revocation 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 DriftAsynchronous direct OpenFGA writes bypassing transactional boundaries or relying on background polling for tuple revocationCritical
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 write relationship tuple mutations to a transactional outbox table within the exact same database transaction as the primary entity state modification.

Engineers MUST ALWAYS write relationship tuple mutations to a transactional outbox table within the exact same database transaction as the primary entity state modification.

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 mutate OpenFGA relationship tuples synchronously in business request handlers prior to committing the primary database transaction.

Engineers MUST NOT mutate OpenFGA relationship tuples synchronously in business request handlers prior to committing the primary database transaction.

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

Engineers MUST enforce time-bound permissions using OpenFGA Conditions with evaluated ISO 8601 timestamps passed via contextual tuples at check-time, rather than relying on delayed cron sweeps for deletion.

Engineers MUST enforce time-bound permissions using OpenFGA Conditions with evaluated ISO 8601 timestamps passed via contextual tuples at check-time, rather than relying on delayed cron sweeps for deletion.

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

CDC consumer services MUST be idempotent, handling duplicate event deliveries via monotonic transaction log sequence numbers (e.g., LSN/Kafka offset tracking) before calling OpenFGA Write/Delete APIs.

CDC consumer services MUST be idempotent, handling duplicate event deliveries via monotonic transaction log sequence numbers (e.g., LSN/Kafka offset tracking) before calling OpenFGA Write/Delete APIs.

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

Authorization checks requiring strict read-after-write consistency MUST supply contextual tuples derived from the active session or uncommitted transaction state when CDC replication lag is detected.

Authorization checks requiring strict read-after-write consistency MUST supply contextual tuples derived from the active session or uncommitted transaction state when CDC replication lag is detected.

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 Temporal Tuple Expiration and CDC Stream Consistency Standard critical for AI coding assistants?

Guarantees zero-lag authorization decisions by synchronizing short-lived contextual access grants with transactional Change Data Capture (CDC) invalidation events. Eliminates race conditions between transactional database state changes and OpenFGA authorization checks by enforcing transactional outbox patterns, context-driven condition validation, and idempotent stream reconciliation. 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 (Asynchronous direct OpenFGA writes bypassing transactional boundaries or relying on background polling for tuple revocation) 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