Documentation
¶
Overview ¶
Package idempotency provides the middleware that makes mutating HTTP requests safely retryable. A request that arrives with an Idempotency-Key header is cached for 24 hours; replay by the same caller with the same key and request returns the cached response without re-running the handler.
The cache is scoped to the calling identity. A cache hit skips the handler, so it also skips every authorization check inside it. Only the caller who created an entry can have it replayed.
Spec: specs/system/idempotency.spec.yaml
Index ¶
Constants ¶
const HeaderName = "Idempotency-Key"
HeaderName is the HTTP header carrying the idempotency key.
const TTL = 24 * time.Hour
TTL is how long a cached response remains valid. Locked in the spec.
Variables ¶
This section is empty.
Functions ¶
func Middleware ¶
Middleware wraps mutating handlers with the idempotency cache.
Behavior (per spec system-idempotency v2.0.0):
- Safe methods (GET/HEAD/OPTIONS) pass through unchanged.
- Missing Idempotency-Key passes through (the handler decides whether the header is required; the middleware doesn't enforce presence).
- An anonymous caller passes through, uncached. See the skip below.
- Cache hit (same actor + same key + same request hash): returns the cached status and a JSON-equal body (JSONB storage normalizes whitespace). Handler is not invoked.
- Cache hit (same actor + same key + different request hash): returns 409 with error.code = "idempotency.key_reused".
- Same key held by a different actor: a plain miss. The handler runs under that caller's own authorization and stores under their own actor. No 409, so the route is not an existence oracle.
- Cache miss: runs handler, captures the response, persists to DB on 2xx. 4xx/5xx are NOT cached (per AC-6 — failures are not pinned).
Types ¶
This section is empty.