Skip to content

[#540] Add concurrency-safe idempotency for charges - #554

Open
arisu6804 wants to merge 1 commit into
Agentpay-Org:mainfrom
arisu6804:feat/issue-540-charge-idempotency
Open

[#540] Add concurrency-safe idempotency for charges#554
arisu6804 wants to merge 1 commit into
Agentpay-Org:mainfrom
arisu6804:feat/issue-540-charge-idempotency

Conversation

@arisu6804

Copy link
Copy Markdown

Summary

Adds a production-shaped charge write path with concurrency-safe, tenant-scoped idempotency for POST /api/v1/charges.

What changed

  • Added a typed ChargeIdempotencyStore contract and atomic in-memory claim state machine.
  • Added canonical fingerprints over method, path, tenant, and charge payload.
  • Added 24-hour replay retention, cloned response replay, conflict detection, and claim release on failed execution.
  • Added tenant-isolated charge storage and a tenant-filtered list endpoint.
  • Added validation for safe idempotency keys, positive safe amounts, currency, source, and description limits.
  • Added OpenAPI route registration and contributor documentation.

Acceptance criteria

  • Same key and same body replays the saved status/body without creating a second charge (src/routes/charges.ts, route test).
  • Same key with a different body returns 409 idempotency_conflict.
  • Concurrent claim returns 409 request_in_progress before a second side effect.
  • Key reuse after the 24-hour TTL is treated as a new request.
  • Missing keys preserve normal at-least-once behavior.
  • Keys are scoped by tenant and cannot collide across tenants.
  • Invalid or oversized keys return a structured 400 response.

Verification

  • npm run build
  • node --test dist/charges.test.js — 17/17 passing
  • npm run lint

The repository-wide legacy test command was also attempted. Existing parallel test-isolation suites report unrelated shared-state/timeouts in this checkout; the new focused suite is deterministic and passes independently.

Operational note

The shipped adapter is intentionally in-memory, as requested by the issue. A multi-process deployment must provide a shared implementation of ChargeIdempotencyStore before relying on exactly-once behavior across process boundaries.

Closes #540

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

idempotency-key support for the charge endpoint with concurrency-safe replay

1 participant