Skip to main content
The Webhook system in Palyra provides a secure mechanism for receiving and processing asynchronous events from external platforms (e.g., Discord, GitHub, custom services). It is designed with a “security-first” approach, incorporating mandatory signature verification, replay protection, and strict payload size limits to protect the Core Daemon from common web-based attack vectors.

Webhook Lifecycle and Data Flow

Webhooks are managed via a WebhookRegistry which persists configuration in a local webhooks.toml file. When an external request arrives, it is validated against an WebhookEnvelope schema, verified for authenticity, and then dispatched to the appropriate internal handler.

Processing Pipeline

  1. Ingress: The HTTP handler receives a raw byte payload.
  2. Envelope Parsing: The payload is parsed into a WebhookEnvelope crates/palyra-common/src/webhook.rs#26-29.
  3. Signature Verification: The WebhookSignatureVerifier uses a secret retrieved from the Vault to verify the HMAC or digital signature crates/palyra-common/src/webhook.rs#27-28.
  4. Replay Protection: The ReplayNonceStore checks the unique nonce and timestamp to prevent replay attacks crates/palyra-common/src/webhook.rs#27-27.
  5. Payload Extraction: If valid, the inner payload is extracted for domain-specific processing crates/palyra-common/src/webhook.rs#26-26.

Webhook Data Flow Diagram

The following diagram illustrates the flow from an external HTTP request to internal processing. Title: Webhook Ingress and Validation Flow Sources: crates/palyra-daemon/src/webhooks.rs#177-187, crates/palyra-common/src/webhook.rs#26-29, crates/palyra-daemon/src/webhooks.rs#52-72

Core Entities and Implementation

WebhookEnvelope

The WebhookEnvelope represents the standard structure for all incoming webhook requests. It enforces versioning via the v field, typically set to CANONICAL_JSON_ENVELOPE_VERSION (currently 1).

WebhookRegistry

The WebhookRegistry handles the persistence and lookup of webhook integrations. It limits the total number of integrations to 1,024 to prevent resource exhaustion crates/palyra-daemon/src/webhooks.rs#17-17.
ConstantValueDescription
MAX_WEBHOOK_COUNT1,024Max integrations in webhooks.toml crates/palyra-daemon/src/webhooks.rs#17-17
MAX_WEBHOOK_PAYLOAD_BYTES1,048,576Hard limit for any webhook payload (1MB) crates/palyra-daemon/src/webhooks.rs#24-24
DEFAULT_MAX_PAYLOAD_BYTES65,536Default limit (64KB) crates/palyra-daemon/src/webhooks.rs#23-23
Sources: crates/palyra-daemon/src/webhooks.rs#15-25

Security: ReplayNonceStore

To prevent attackers from capturing a valid webhook and re-sending it, Palyra implements ReplayProtection. The ReplayNonceStore tracks nonces within a specific time window. If a nonce is seen twice or the timestamp is too old/too far in the future, the request is rejected. Sources: crates/palyra-common/src/webhook.rs#27-27

CLI Webhooks Commands

The palyra CLI provides a complete suite of commands for managing webhooks, located in crates/palyra-cli/src/commands/webhooks.rs.
CommandFunctionKey Arguments
listLists all configured webhooks--provider, --enabled
addCreates a new integration--integration-id, --secret-vault-ref, --require-signature
testSimulates an incoming payload--payload-file, --payload-stdin
removeDeletes an integration--integration-id
enable/disableToggles active state--integration-id

CLI to Daemon Communication

The CLI interacts with the daemon’s Admin API. For example, the test command encodes the payload as Base64 before sending it to the test_webhook endpoint crates/palyra-cli/src/commands/webhooks.rs#100-110. Title: Webhook Management Logic Mapping Sources: crates/palyra-cli/src/commands/webhooks.rs#12-15, crates/palyra-cli/src/commands/webhooks.rs#36-63, crates/palyra-cli/src/commands/webhooks.rs#100-110

JSON Schema (webhook-envelope.v1.json)

The system enforces a strict JSON schema for the WebhookEnvelope. Key requirements include:
  1. v: Must be 1 crates/palyra-common/src/lib.rs#32-32.
  2. integration_id: Must match a configured ID in the registry.
  3. signature: Required if signature_required is true in the record crates/palyra-daemon/src/webhooks.rs#41-41.
  4. nonce: Required for replay protection.
Sources: crates/palyra-common/src/lib.rs#31-33, crates/palyra-daemon/src/webhooks.rs#52-72