Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions MIGRATION_v7_to_v8.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,16 @@ that task does not share the server lifecycle.

The registry commits terminal state and the immutable prepared webhook in one
explicit transaction, including when the supplied pool uses autocommit. The
body and callback token are AES-256-GCM encrypted at rest and bound to the task,
account, URL, operation, status, and idempotency key. The retry horizon starts
at the first delivery attempt; the worker replays the same body/key and retains
proof until that exact advertised horizon ends.
body, callback token, and any explicit legacy authentication selector and
credentials are AES-256-GCM encrypted at rest and bound to the task, account,
URL, operation, status, and idempotency key. When
`push_notification_config.authentication` is present, the outbox emits the
selected Bearer or HMAC-SHA256 mode; when absent, it emits RFC 9421. The retry
horizon starts at the first delivery attempt; the worker replays the same
body/key and retains proof until that exact advertised horizon ends. Enable
HMAC only by setting `legacy_hmac_fallback=True` on the outbox and advertising
the matching `webhook_signing.legacy_hmac_fallback=true` capability; boot
validation rejects either side being enabled alone.

SDK-managed publication requires the exact `PgTaskRegistry` and
`PgTaskWebhookOutbox` types. Subclasses are rejected because overriding task
Expand Down Expand Up @@ -160,6 +166,15 @@ networks may temporarily retain unsigned legacy callbacks with
`allow_unauthenticated_webhooks=True`; multi-agent clients must scope this
escape by agent ID.

## Scheduled reporting webhook correlation

`ReportingWebhook.operation_id` is now required. Buyers must assign it when
creating or updating a reporting registration, and sellers must echo it
verbatim in every scheduled `McpWebhookPayload`. Existing persisted reporting
registrations have no conforming value to migrate automatically: flag or skip
those rows until the buyer supplies an operation ID. Do not derive one from a
media buy ID or callback URL.

## Webhook activity metadata

`ActivityType.WEBHOOK_RECEIVED` no longer copies the complete callback into
Expand Down
5 changes: 4 additions & 1 deletion SCHEMA_DELTAS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Generated-types delta

_No field-shape changes detected._
## Field changes

- `core/reporting_webhook.py`
- `ReportingWebhook`: `+operation_id`
17 changes: 12 additions & 5 deletions docs/handler-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -1438,13 +1438,20 @@ and encryption key; multiple replicas are safe. Avoid an
unretained `create_task()` beside synchronous `serve()`, because it is not tied
to the server's startup/shutdown lifecycle.

The task registry captures URL, buyer-supplied `operation_id`, and token as an
encrypted, authenticated registration when the task is issued. Its
The task registry captures URL, buyer-supplied `operation_id`, token, and any
explicit legacy authentication selector and credentials as an encrypted,
authenticated registration when the task is issued. Presence of
`push_notification_config.authentication` selects Bearer or HMAC-SHA256;
absence selects the configured RFC 9421 sender. HMAC-SHA256 is admitted only
when both `PgTaskWebhookOutbox(legacy_hmac_fallback=True)` and the advertised
`webhook_signing.legacy_hmac_fallback` capability are true. Resolver-based
deployments can preserve hardened legacy egress policy with
`legacy_allowed_destination_ports=` and `legacy_transport_hooks=`. Its
`complete()` / `fail()` transaction writes terminal
state and the encrypted, authenticated webhook envelope together. The task-row
copy of the callback token is cleared in that transaction. Workers use expiring
leases and exact retries; the 1–7 day horizon begins on the first attempt and
must exactly match the advertised value.
copy of the callback registration is cleared in that transaction. Workers use
expiring leases and exact retries; the 1–7 day horizon begins on the first
attempt and must exactly match the advertised value.

### Multi-tenant webhook signing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -436,6 +443,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -674,4 +682,4 @@
"generatedAt": "2026-08-23T20:02:49.185Z",
"note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory."
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6185,6 +6185,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -6286,6 +6293,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -6851,4 +6859,4 @@
"generatedAt": "2026-08-23T20:02:49.545Z",
"note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory."
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5070,6 +5070,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -5171,6 +5178,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -5694,4 +5702,4 @@
"generatedAt": "2026-08-23T20:02:49.565Z",
"note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory."
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49983,6 +49983,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -50034,6 +50041,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -100280,4 +100288,4 @@
"generatedAt": "2026-08-23T20:02:49.684Z",
"note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory."
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93089,6 +93089,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -93140,6 +93147,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -95439,4 +95447,4 @@
"generatedAt": "2026-08-23T20:02:50.403Z",
"note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory."
}
}
}
4 changes: 2 additions & 2 deletions schemas/cache/3.2.0-beta.6/core/mcp-webhook-payload.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
},
"operation_id": {
"type": "string",
"description": "Client-generated correlation identifier for the operation that produced this webhook. Buyers supply this value at webhook registration time via `push_notification_config.operation_id`; sellers MUST echo it verbatim in every webhook payload. Sellers MUST NOT derive `operation_id` by parsing `push_notification_config.url` \u2014 the URL is opaque to the seller. Receivers MAY dispatch endpoints by URL path or query string, but MUST correlate the operation using this payload field, not URL-derived values. See [Webhooks \u2014 Operation IDs and URL templates](/docs/building/by-layer/L3/webhooks#operation-ids-and-url-templates) for the full normative wire contract."
"description": "Client-generated correlation identifier for the operation that produced this webhook. Buyers supply this value at webhook registration time via `push_notification_config.operation_id` or, for scheduled delivery reports, `reporting_webhook.operation_id`; sellers MUST echo it verbatim in every webhook payload. Sellers MUST NOT derive `operation_id` by parsing either registration URL \u2014 URLs are opaque to the seller. Receivers MAY dispatch endpoints by URL path or query string, but MUST correlate the operation using this payload field, not URL-derived values. See [Webhooks \u2014 Operation IDs and URL templates](/docs/building/by-layer/L3/webhooks#operation-ids-and-url-templates) for the full normative wire contract."
},
"task_id": {
"type": "string",
Expand Down Expand Up @@ -216,4 +216,4 @@
}
}
]
}
}
10 changes: 9 additions & 1 deletion schemas/cache/3.2.0-beta.6/core/reporting-webhook.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -60,8 +67,9 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
"additionalProperties": true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -477,6 +484,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -696,4 +704,4 @@
"additionalProperties": true
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4544,6 +4544,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -4595,6 +4602,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -4802,4 +4810,4 @@
"additionalProperties": true
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3512,6 +3512,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -3563,6 +3570,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand Down Expand Up @@ -3692,4 +3700,4 @@
"additionalProperties": true
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9299,6 +9299,13 @@
"format": "uri",
"description": "Webhook endpoint URL for reporting notifications"
},
"operation_id": {
"type": "string",
"description": "Buyer-supplied correlation identifier for scheduled reporting webhooks. The seller MUST echo this value verbatim into every McpWebhookPayload operation_id field for this registration and MUST NOT derive or fabricate it from media_buy_id or the callback URL. Buyers SHOULD generate a stable unique value for each reporting registration.",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_.:-]{1,255}$"
},
"token": {
"type": "string",
"description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.",
Expand Down Expand Up @@ -9350,6 +9357,7 @@
},
"required": [
"url",
"operation_id",
"authentication",
"reporting_frequency"
],
Expand All @@ -9361,4 +9369,4 @@
"total_budget"
]
}
}
}
Loading
Loading