ExDaytona.Webhooks.Plug (ex_daytona v0.4.0)

Copy Markdown View Source

A drop-in endpoint for receiving Daytona webhook deliveries.

Signature verification needs the raw request body, which is a notorious footgun behind Plug.Parsers (the body is consumed and re-encoding breaks the signature). This plug closes the loop: mount it above Plug.Parsers with :at, and it reads the raw body, verifies the Svix signature via ExDaytona.Webhooks.verify/4, invokes your handler, and answers with the status the provider's retry logic expects — while every other request passes through untouched.

In a Phoenix endpoint (before plug Plug.Parsers):

plug ExDaytona.Webhooks.Plug,
  at: "/webhooks/daytona",
  secret: {MyApp.Config, :daytona_webhook_secret, []},
  handler: MyApp.DaytonaWebhooks

In a bare Plug.Router, the same options work with plug ... when action-style mounting, or omit :at when the plug terminates a dedicated pipeline that only ever sees webhook traffic.

Options

  • :secret (required) — the endpoint's signing secret (whsec_...): a binary, a {module, function, args} tuple, or a zero-arity fun (both resolved per request, so runtime configuration works)
  • :handler (required) — who receives verified events: a module implementing ExDaytona.Webhooks.Handler, a {module, function} tuple called as function(event, conn), or a fun of arity 1 (event) or 2 (event, conn)
  • :at — request path to handle; other paths pass through untouched. Omit to handle every request reaching the plug.
  • :tolerance_seconds — max timestamp skew (default 300)
  • :max_body_bytes — reject larger deliveries with 413 (default 1_048_576)

Responses

  • 204 — signature valid, handler returned :ok/{:ok, _}
  • 400 — missing/invalid signature headers, stale timestamp, or signature mismatch (the provider will not retry a 4xx)
  • 405 — non-POST request at :at
  • 413 — body exceeded :max_body_bytes
  • 500 — handler returned {:error, _} or raised (the provider retries the delivery later)

This module is compiled only when the optional :plug dependency is present.