Skip to content

feat(webhooks): add lifecycle-event webhooks support - #4

Open
col wants to merge 8 commits into
mainfrom
feat/webhooks
Open

feat(webhooks): add lifecycle-event webhooks support#4
col wants to merge 8 commits into
mainfrom
feat/webhooks

Conversation

@col

@col col commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Summary

Adds support for the E2B lifecycle-event webhooks API — both halves:

  • Outbound management (E2bEx.Webhooks) — CRUD over /events/webhooks (list/1, create/2, get/2, update/3, delete/2), mirroring the existing E2bEx.Volumes resource and funnelling through the single E2bEx.Request HTTP chokepoint. Decoded into the new E2bEx.Webhook struct.
  • Inbound delivery (E2bEx.WebhookEvent) — a pure, HTTP-free module that decodes the delivered (snake_case) event payload and verifies its signature:
    • verify_signature/3 — plain SHA256 of secret <> raw_body, standard base64, trailing = stripped, constant-time compared to the e2b-signature header.
    • parse/3 — verify-then-decode → {:ok, %WebhookEvent{}} | {:error, :invalid_signature | :invalid_payload}.

Notes

  • These endpoints are not in openapi.yml (absent from both this repo's copy and upstream E2B's), and the JS/Python SDKs don't implement webhook management either. Source of truth is the E2B docs. Recorded as a gotcha in CLAUDE.md.
  • Deliberate divergences (documented in CLAUDE.md): the inbound payload is already snake_case so WebhookEvent.from_api/1 reads keys directly (no camelCase conversion); and parse/3 returns atom error reasons rather than %E2bEx.Error{}, since signature/JSON validation is local, not an HTTP failure (mirrors how Commands diverges).
  • create/2/update/3 return {:error, %E2bEx.Error{reason: :empty_response_body}} instead of crashing if the API returns an empty body (the response shape for these is unconfirmed).

Process

Built via the project's superpowers workflow: specplan → subagent-driven TDD, with per-task spec+quality reviews and a final whole-branch review.

Test plan

  • mix test150 tests, 0 failures.
  • mix compile --warnings-as-errors — clean.
  • New coverage: CRUD (method/path/body/decode + non-2xx error + empty-body error), WebhookEvent.from_api/1 decoding, and signature/parse cases (valid, tampered body, wrong secret, length mismatch, non-JSON-with-valid-sig).

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant