Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.manthan.systems/llms.txt

Use this file to discover all available pages before exploring further.

What is replay protection?

Replay protection ensures that identical signals cannot produce two separate governed decisions using the same replay store. Each execution_fingerprint can only be consumed once - ever. This is essential for governed decisions that cause consequential state transitions: approving a payment, escalating a case, deploying infrastructure. The governance runtime enforces single-use execution at the atomic level.

How it works

Parmana uses a two-phase commit protocol for replay protection:
  1. Compute the execution_fingerprint - sha256(canonicalize(signals))
  2. Reserve the fingerprint in the replay store (phase 1)
  3. Evaluate the policy and sign the decision
  4. Confirm the fingerprint in the replay store (phase 2)
If the store is unavailable at step 2, execution is blocked - fail-closed by design. If it fails at step 4, the caller receives an error and must not retry automatically. A second call with the same signals throws INV-013:
[INV-013@replay] Replay detected: execution_fingerprint <hash> has already been consumed

MemoryReplayStore vs RedisReplayStore

MemoryReplayStoreRedisReplayStore
PersistenceIn-process onlyPersists across restarts
Multi-processNoYes
Use caseDevelopment and testingProduction
SetupNoneRedis instance
MemoryReplayStore emits a warning when NODE_ENV=production. It loses all replay protection state on process restart and does not work across multiple processes. Use RedisReplayStore in production.

RedisReplayStore setup

import { RedisReplayStore } from "@parmanasystems/core";

const store = new RedisReplayStore({
  host: process.env.REDIS_HOST,
  port: parseInt(process.env.REDIS_PORT ?? "6379"),
});

What the fingerprint covers

The execution_fingerprint is derived from the canonicalized signals only - not from timestamps, trace IDs, or request metadata:
const execution_fingerprint = sha256(canonicalize(signals));
This means:
  • Same signals = same fingerprint = replay rejected
  • Different signals = different fingerprint = new execution
  • Key ordering and whitespace do not affect the fingerprint

INV-013 in practice

Replay detection is intentional, not an error in your code. Common causes:
CauseFix
Client retrying a failed request with the same signalsUse idempotency at the application layer; don’t re-execute with the same signals
Testing with the same signals repeatedlyUse new MemoryReplayStore() per test to reset state
Distributed nodes sharing a MemoryReplayStoreSwitch to RedisReplayStore

Error codes

CodeMeaning
INV-013Replay detected - execution_fingerprint already consumed

See also