Expand description
Push notifications: telling a peer’s webhook that its task moved.
Streaming holds a connection open; push does not. A peer that asked for a task at 09:00 and disconnected wants to know at 14:00 that it finished, and neither polling forever nor holding a socket for five hours is a reasonable way to arrange that.
§The URL comes from the caller, which is the whole problem
Every other outbound destination in this crate is granted by an operator. A webhook URL is supplied by whoever created the task — so push is the one feature where an untrusted party names an address this plane will connect to, with a payload describing somebody’s task.
Three controls, and none of them is sufficient alone:
- An operator grant. The host must be on an allowlist. A caller may pick any URL under a host the deployment permits, and no host it does not. This is the primary control; the rest are the second lock.
- Public addresses only. Every destination is checked with
netguardbefore dispatch, and every name the client resolves is checked again as it resolves — so a host that resolves inward, or answers differently the second time, reaches nothing. - HTTPS only. The payload describes a task; sending it in clear to an address chosen by the recipient is a disclosure with extra steps.
§What is delivered, and what is not
The payload is a StreamResponse — the same status/artifact union streaming
sends, so a receiver parses one thing and A2A’s two delivery mechanisms do
not disagree. Registering a destination is therefore authorization to send
that task’s output there: task-level policy and the operator host grant are
both checked rather than treating the allowlist as sufficient authority.
What that union is called on the wire is the PushMessage’s to say, not
this module’s: the same loop also carries an operator’s structured-mode
CloudEvents envelope, and one hard-coded media type would make whichever
of the two lost a body no conformant receiver routes.
§The journal is the outbox
A registration stores the first journal sequence it has not acknowledged.
Workers derive payloads from those records and advance only after HTTP 2xx.
A crash after POST but before cursor persistence duplicates an event instead
of losing it, which is A2A’s at-least-once contract — and why every delivery
carries a HEADER_ID the receiver can recognise a repeat by.
A receiver that answers permanently, or that stays silent past the retry ceiling, has its registration parked rather than deleted. The cursor is the only record of how far that receiver got; discarding it turns a receiver outage into an unrecoverable gap, where keeping it turns the same outage into a list an operator can re-arm.
Structs§
- Body
Signing - A shared signing key.
- Delivery
Worker - Durable outbound delivery, driven by an operator’s scheduler.
- Destination
- One place the deployment sends its own events.
- DueBatch
- One namespace’s due registrations, with the other namespace’s backlog counted rather than silently skipped.
- Outbox
- The operator’s destinations, and the registration that puts a run in front of them.
- Push
Authentication - Authentication information from A2A’s push configuration.
- Push
Config - Where a peer wants to be told about a task.
- Push
Message - One POST’s worth of body: what to send, and what it is.
- Push
Policy - Which webhook destinations this deployment permits.
- Push
Registration - One durable delivery cursor.
- Push
Sender - Delivers notifications, under the controls in the module docs.
- Push
Sweep Report - Outcome of one bounded delivery sweep.
- RunCompleted
- One
CloudEventsmessage per completed run. - Verified
Delivery - A delivery that verified.
- Webhook
Verifier - The check that
BodySigningis one half of.
Enums§
- Delivered
- What happened to one delivery attempt.
- Push
Error - Why a webhook was not accepted or not delivered.
- Push
Namespace - Which of the two id namespaces a worker serves.
- Signing
KeyError - A signing secret this deployment wrote about itself that cannot be used.
- Webhook
Rejected - Why a delivery was not accepted.
Constants§
- DEFAULT_
TOLERANCE - How far a delivery’s timestamp may sit from now, in either direction.
- HEADER_
A2A_ TOKEN - A2A’s opaque per-task token, echoed on every delivery for the receiver that registered it to validate against.
- HEADER_
ID - The message’s own identity, and the receiver’s idempotency key.
- HEADER_
SIGNATURE v1,<base64>over{id}.{timestamp}.{body}— one element per configured key, space-separated.- HEADER_
TIMESTAMP - Unix seconds at which this attempt was made.
- MIN_
KEY_ BYTES - The shortest key this accepts, in bytes.
- OPERATOR_
PREFIX - The marker that tells an operator destination from a caller’s webhook.
- SCHEME
- The one signature label this build produces and checks.
Traits§
- Projection
- What one journal record should be delivered as.
- Push
Store - Durable storage for webhook registrations.
- Push
Transport - Delivery transport used by the durable worker.
Functions§
- is_
operator_ id - Whether a registration id names an operator destination.