Skip to content

Add contract-declared HTTP idempotency - #244

Merged
andrewzolotukhin merged 2 commits into
developmentfrom
feat/endpoint-idempotency
Oct 4, 2026
Merged

andrewzolotukhin merged 2 commits into
developmentfrom
feat/endpoint-idempotency

Conversation

@andrewzolotukhin

@andrewzolotukhin andrewzolotukhin commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Original request

Declare HTTP idempotency in the endpoint contract so a typed client can retry a request without executing the server mutation twice. Keep ordinary client calls unchanged and deliver the library changes against development.

What changed

  • Add .idempotent() to mutation contracts. The client automatically creates one request key and preserves it, along with the serialized body, across configured HTTP retries. Separate client invocations get separate keys.
  • Use contract metadata for retry eligibility and batching bypass, including binary/streaming response modes. Existing explicit retry restrictions and retry opt-out still apply.
  • Register typed server preparation and identity-scoping callbacks. Authentication, validation, and application authorization run before every replay; concurrent requests share the original response. Bound error policies also handle preparation failures.
  • Generate the optional replay header and transport Problem Details in OpenAPI without overwriting domain response schemas. Update current documentation and add a minor changeset.

Reasoning

The contract identifies mutations safe for transport retries. Consumers keep normal endpoint calls and their shared retry middleware; the server owns response replay. Applications retain their resource authorization and verified user/tenant scope.

The existing low-level middleware remains available. Replay is bounded and process-local, using the existing 24-hour / 1,000-entry / 65,536-byte defaults per endpoint. Reusing a key asserts identical input. Restarts, expiry, separate replicas and thrown failures are outside a durable exactly-once guarantee. CORS remains an explicit application policy.

This change does not add form/session attempt tracking or manual retry APIs.

Blog post

Not applicable: this is a library API change. The client/server READMEs, documentation site and changeset describe the supported behavior.

Screenshots / preview evidence

Screenshots are not applicable to the HTTP transport behavior. No hosted PR preview is configured. Automated tests cover same-key concurrency, authorization, scope isolation, response capture, explicit batching, automatic retries and fresh keys for separate calls.

Validation

  • npm run lint
  • npm run build
  • npm run test: 265 files, 5,115 tests; no type errors.
  • npm run typecheck:schema-site and npm run typecheck:docs-site
  • npm run test:packages: 22 packages, 52 entry points; declarations, licenses and browser bundle passed.
  • All GitHub checks passed on 637356f2: Node 24 lint/build/tests/coverage, dependency audit, packed packages, website builds/API references, PostgreSQL integration, S3 storage integration and demo API/browser/telemetry E2E.
  • Consumer validation with local packages passed: complete build/typecheck/unit tests, 61 PostgreSQL cases in two timezones, and production-build HTTP replay/OpenAPI browser checks.
  • PR-ready notification is skipped: this library PR has no hosted preview environment URL.
  • External SigNoz verification is skipped because this library PR has no hosted telemetry environment. CI runs the isolated demo API/browser/telemetry checks.

@andrewzolotukhin andrewzolotukhin changed the title Add contract idempotency and reusable save attempts Add contract-declared HTTP idempotency Oct 4, 2026
@andrewzolotukhin
andrewzolotukhin merged commit 4d5efff into development Oct 4, 2026
4 checks passed
@andrewzolotukhin
andrewzolotukhin deleted the feat/endpoint-idempotency branch October 4, 2026 16:41
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.

1 participant