prompts / webhook-receiver.md
edit FILL IN & copy this prompt →860 words

Prompt: receive third-party webhooks on your dev machine at a stable URL

Have an agent give a local dev server a permanent public HTTPS address for Stripe, GitHub, Twilio or any other webhook sender — through an ird tunnel that survives reboots via the background agent — with signature verification wired in locally, a way to tell "the tunnel was down" from "my handler failed", and a teardown that actually stops the bill.

Needs: the ird CLI logged in on the machine that runs the dev server (the MCP server can create the tunnel, but forwarding runs where the app is); a hostname on a zone hosted on ird DNS; access to the provider's dashboard Costs: hourly while the tunnel exists (credits_prices → recurring.tunnel-hourly), plus per MB stored if a custom offline page is set (recurring.ipfs-pin-hourly) Group: developer workflow

Paste everything below the line into a fresh conversation. Fill in the FILL IN block first.


Task

Expose the local route below at https://HOST/PATH, keep it reachable across restarts, register it at PROVIDER with signature verification, and delete the tunnel when I say so. Nothing is created before I confirm the hourly cost.

FILL IN

HOST:        hooks.example.ro           # hostname on a zone hosted on ird DNS
PORT:        4000                       # local port the dev server listens on
PATH:        /webhooks/stripe           # route the provider will POST to
PROVIDER:    stripe                     # stripe | github | twilio | other (name it)
EVENTS:      checkout.session.completed # what to subscribe to at the provider
SECRET_VAR:  STRIPE_WEBHOOK_SECRET      # env var holding the signing secret
OFFLINE:     standard                   # or a folder with index.html, served while offline

Non-negotiable rules

  1. Hourly until deleted. Bills from creation until delete; ird tunnels stop and ird agent stop only stop forwarding, the tunnel keeps billing. Show hourly and hourly × 730 from credits_prices before creating, wait for a yes.
  2. Never trust an unsigned payload. Verify the provider's signature over the raw body before doing anything. The signing secret lives in SECRET_VAR (a local .env, not committed), never in chat, logs or the repo.
  3. One tunnel per hostname. list_tunnels first; reuse an existing one on HOST rather than creating a second.
  4. Only expose a listening port. curl -sI http://127.0.0.1:PORT must answer first.
  5. The provider dashboard is mine. Give me the exact values to enter; never use provider API keys I didn't hand you.

Steps

A. Preflight. dns_list_zones must include HOST's zone (else stop: register-domain / bring-domain-dns prompts). list_tunnels for an existing one. Rules 4 and 1.

B. Create and keep connected. On the dev machine:

ird tunnel HOST PORT
ird agent start
ird agent autostart on

ird tunnel creates the tunnel, writes the DNS record and starts forwarding; the agent keeps it connected, autostart on restores it at login. Check ird agent status and ird tunnels status HOST. MCP-only: create_tunnel(hostname=HOST, ssh_public_key=<device key>) returns the ssh_command the device runs — relay verbatim.

C. Register at PROVIDER. URL https://HOST/PATH, events EVENTS; secret into SECRET_VAR:

D. Verify locally. In the handler: read the raw body (before any JSON middleware), verify with the provider's SDK or HMAC helper using SECRET_VAR, 400 on mismatch, return 2xx fast, do the work asynchronously. Log headers and raw body of every request to a file: ird tunnels logs shows forwarder events only (connected, disconnected, "nothing is listening on localhost:PORT"), never requests.

E. Test end to end. Trigger a test delivery (Stripe "send test event", GitHub "Redeliver" on the ping, Twilio a real call/SMS). Expect: list_tunnels shows HOST active, your log shows a validly signed request, the provider's delivery log shows 2xx. Then tamper one byte of a replay and confirm a 400.

F. Offline behaviour. If OFFLINE is a folder: tunnel_set_offline(tunnel=HOST, path=<absolute folder>) (CLI: ird tunnel offline HOST ./folder) — served whenever the forwarder is not connected, effective within a minute. Laptop closed = the provider reaches that page, not your handler. Its HTTP status is undocumented, so test once: ird tunnels stop HOST, redeliver, read the provider's log, restart. A recorded 2xx means missed events must be reconciled from the provider's API; a failure means redeliver from its dashboard once ird agent status shows forwarding. ird tunnels logs timestamps every drop and reconnect.

G. Teardown (when I say "done"). Remove the endpoint at PROVIDER first (or it keeps retrying), then delete_tunnel(tunnel_id) from list_tunnels (CLI: ird tunnels delete HOST) — billing stops immediately, the hostname stops serving. DNS and offline-page cleanup are undocumented: dns_get_zone, dns_delete_record a leftover HOST record; if OFFLINE was a folder, ipfs_pins → ipfs_unpin any surviving pin. ird agent autostart off if this was its only tunnel.

Deliverable

https://HOST/PATH, the tunnel id and status, the agent status line, hourly/monthly cost, the provider-side settings (URL, events, header name — never the secret), the test-delivery result, and the one-line teardown command.

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/prompts.git