Skip to content

docs(order): sign Webhook-Id, Webhook-Timestamp, and UCP-Agent in the webhook signature - #659

Open
vishkaty wants to merge 1 commit into
Universal-Commerce-Protocol:mainfrom
vishkaty:fix/webhook-sign-standard-headers
Open

docs(order): sign Webhook-Id, Webhook-Timestamp, and UCP-Agent in the webhook signature#659
vishkaty wants to merge 1 commit into
Universal-Commerce-Protocol:mainfrom
vishkaty:fix/webhook-sign-standard-headers

Conversation

@vishkaty

@vishkaty vishkaty commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Problem

The order event webhook lists Webhook-Id and Webhook-Timestamp as required headers and states that headers follow Standard Webhooks, but the signing and verification steps never cover them, and the example Signature-Input signs only @method, @authority, @path, content-digest, and content-type.

Webhooks carry no Idempotency-Key, so Webhook-Id and Webhook-Timestamp are the only per-delivery replay signal. As written, a captured, validly signed delivery can be replayed with an altered Webhook-Id or Webhook-Timestamp, defeating any dedup or freshness check keyed on them.

Fix

The overview verification gate is a closed set (ucp-agent, signature-agent, idempotency-key) with the clause "a header added to UCP later is gate-required only if its defining section says so." This PR has the order webhook section say so:

  • Webhook-Id and Webhook-Timestamp MUST be covered components; platforms MUST verify their coverage and MUST deduplicate on Webhook-Id.
  • Update the signing and verification steps and the example Signature-Input accordingly.

The example also now covers ucp-agent. The overview gate already requires it whenever the UCP-Agent header is present, and the example carried the header without covering it; adding it binds the signer identity on the webhook. This subsumes the webhook-example change proposed in #568 (that PR additionally covers ucp-agent in a checkout-rest.md request example, which is left to it).

It also drops the stale event_id/created_time from the example body and the playground payload builder (moved to headers in #342), and shows the required headers in the example.

Verification

validate_examples.py and ucp-schema lint unaffected (the change touches an http example and prose, not validated JSON). Playground eventId/eventTime remain used elsewhere (no dead vars).

@damaz91 damaz91 added the status:needs-triage Signal that the PR is ready for human triage label Jul 31, 2026
… webhook signature

The order event webhook lists Webhook-Id and Webhook-Timestamp as required
headers and states that headers follow Standard Webhooks, but the signing and
verification steps never cover them, and the example Signature-Input signs only
method, authority, path, content-digest, and content-type. Webhooks carry no
Idempotency-Key, so these headers are the only per-delivery replay signal; as
written a captured, validly signed delivery can be replayed with an altered
Webhook-Id or Webhook-Timestamp.

The overview verification gate already anticipates this: a header outside the
default covered set is gate-required when its defining section says so. Have the
order webhook section say so for webhook-id and webhook-timestamp, require
platforms to verify their coverage, and require deduplication on Webhook-Id.
Update the signing and verification steps and the example accordingly.

The example also now covers ucp-agent, which the overview gate already requires
whenever the UCP-Agent header is present (it was missing from this example); this
binds the signer identity on the webhook and subsumes the webhook-example change
in Universal-Commerce-Protocol#568. Also drop the stale event_id and created_time from the example body and
the playground payload builder (moved to headers in Universal-Commerce-Protocol#342), and show the required
Webhook-Id and Webhook-Timestamp headers in the example.
@vishkaty
vishkaty force-pushed the fix/webhook-sign-standard-headers branch from d05b53d to f6f69b4 Compare July 31, 2026 23:12
@vishkaty vishkaty changed the title docs(order): require webhook signatures to cover Webhook-Id and Webhook-Timestamp docs(order): sign Webhook-Id, Webhook-Timestamp, and UCP-Agent in the webhook signature Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:needs-triage Signal that the PR is ready for human triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants