Skip to content

fix(cors): allow Idempotency-Key header for the jobs API - #198

Merged
TaprootFreak merged 1 commit into
stagingfrom
feat/cors-idempotency-key
Jun 4, 2026
Merged

fix(cors): allow Idempotency-Key header for the jobs API#198
TaprootFreak merged 1 commit into
stagingfrom
feat/cors-idempotency-key

Conversation

@TaprootFreak

Copy link
Copy Markdown
Contributor

Root cause

The jobs-API admit handlers (POST /api/jobs/mint, POST /api/jobs/send) require the Idempotency-Key request header (read_idempotency_key). When a browser sends that header it first issues a CORS preflight (OPTIONS). The router's CorsLayer only listed Content-Type in Access-Control-Allow-Headers, so the preflight was rejected and the browser blocked the request — the web frontend could not mint or send.

Fix

Add idempotency-key to the CORS allow_headers list in create_router (node/src/router.rs). HeaderName::from_static requires the lowercase form. Minimal change, no scope creep.

.allow_headers([
    header::CONTENT_TYPE,
    header::HeaderName::from_static("idempotency-key"),
]);

Test

New CORS preflight test in node/src/router_tests.rs: sends OPTIONS /api/jobs/mint with Origin, Access-Control-Request-Method: POST and Access-Control-Request-Headers: idempotency-key, then asserts the response's Access-Control-Allow-Headers echoes both idempotency-key and content-type (case-insensitive). The CorsLayer answers the preflight itself.

Local verification

  • cargo fmt --all -- --check: clean
  • cargo clippy all three feature scopes (-p node -p shared, -p node --all-features, program+prover --lib) with -D warnings: clean
  • Coverage gate (cargo llvm-cov nextest --release -p node -p shared --all-features ... --fail-under-lines 100 --fail-under-functions 100 -E 'not binary(api_remote)'): exit 0 — 443/443 tests passed; router.rs lines 100%, functions 100%
  • New CORS preflight test: PASS

…the jobs API

The jobs-API admit handlers (`POST /api/jobs/mint`, `POST /api/jobs/send`)
require the `Idempotency-Key` request header (`read_idempotency_key`). A
browser sending that header triggers a CORS preflight (OPTIONS), but the
router's `CorsLayer` only allowed `Content-Type` in
`Access-Control-Allow-Headers`. The preflight therefore failed and the
web frontend could not mint or send.

Add `idempotency-key` to the CORS `allow_headers` list so the preflight
succeeds. `HeaderName::from_static` requires the lowercase form.

Cover the fix with a CORS preflight test (`OPTIONS /api/jobs/mint` with
`Access-Control-Request-Headers: idempotency-key`) asserting the response
echoes both `idempotency-key` and `content-type` in
`Access-Control-Allow-Headers`.
@TaprootFreak
TaprootFreak marked this pull request as ready for review June 3, 2026 22:44
@TaprootFreak TaprootFreak added the ci:full Trigger heavy CI jobs (Server + Shared Tests + Coverage Gate, ~60-90 min on M3 Ultra) label Jun 3, 2026
@TaprootFreak
TaprootFreak merged commit 543c1bf into staging Jun 4, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:full Trigger heavy CI jobs (Server + Shared Tests + Coverage Gate, ~60-90 min on M3 Ultra)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant