Skip to content

guiwohl/relay

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Relay

Webhook delivery infrastructure. Register a destination endpoint, push events over the API, and Relay signs each delivery with HMAC-SHA256, retries failures with exponential backoff, dead-letters what won't deliver, and lets you replay any of it from a dashboard. Multi-tenant SaaS with session + API-token auth and Stripe billing.

Portfolio project — a real, working MVP, not a toy. The reliability core (signing, retry/backoff, idempotency, dead-letter, replay) is genuinely implemented and tested.

What it does

  • Sign — every delivery carries X-Relay-Signature: sha256=<HMAC> over "{timestamp}.{body}" with the endpoint's secret, so the destination can verify authenticity and reject replays.
  • Retry with backoff — failed deliveries retry up to 5 times with exponential backoff (0, 2, 4, 8, 16s), each attempt logged with its next_retry_at.
  • Dead-letter — once attempts are exhausted the event is marked dead-lettered.
  • Replay — a manual action re-runs delivery from a clean slate when the destination is healthy again.
  • Idempotent ingestion — an Idempotency-Key header dedupes retried sends.

Tech stack

Layer Choice
Framework PHP 8.4 · Laravel 12
Frontend Inertia 2 · React 19 · Tailwind · shadcn/ui (Laravel React starter kit)
Queue / worker Laravel Horizon + Redis (DeliverWebhook jobs)
Data PostgreSQL 18 · Redis
Auth Session (dashboard) · Sanctum bearer tokens (ingestion API)
Billing Laravel Cashier (Stripe, test mode) — Billable on the Tenant
Infra Laravel Sail · ./relay CLI · Pint · PHPUnit

Row-level multi-tenancy (tenant_id FK, a BelongsToTenant global scope).

Architecture

                    dispatch     ┌───────┐
  client ─POST─▶ Laravel app ──▶ │ redis │
                    │  job        └───┬───┘
                    │  inserts        │ pop
              ┌─────▼─────┐      ┌─────▼─────┐  signed POST
              │  pgsql    │◀─────│  horizon  │ ───────────▶ your endpoint
              └───────────┘  log └───────────┘   retry/backoff/dead-letter
                              every attempt
   dashboard (Inertia/React) ─▶ app    (only the app is exposed to the host)

Full design — data model, retry algorithm, signing scheme, idempotency — is in docs/decisions/0001-architecture.md.

Quick start

git clone https://github.com/guiwohl/relay && cd relay
cp .env.example .env
./relay artisan key:generate     # or paste an APP_KEY
./relay init                     # build, boot, install deps, build assets, migrate + seed

Open the dashboard at http://localhost:8081 (change with APP_PORT in .env). Horizon is at /horizon. The seeder creates demo@relay.test / password. Only the app is exposed to the host; pgsql/redis live on the internal Docker network. For a stable URL, point portless at the app container to get https://relay.localhost.

Common commands: ./relay horizon · ./relay test · ./relay lint · ./relay tinker · ./relay down. Run ./relay with no args for the full list.

The end-to-end retry/replay demo is scripted in docs/runbooks/local-dev.md.

Billing demo needs your Stripe test keys

Billing code is real (Cashier Checkout Session + signature-verified webhook). The live demo needs your own Stripe test-mode keys in .env (STRIPE_KEY, STRIPE_SECRET, STRIPE_PRICE_ID, STRIPE_WEBHOOK_SECRET). Automated tests don't call Stripe for checkout but exercise the webhook signature path for real, so ./relay test needs no keys.

Tests

./relay test runs the PHPUnit suite (SQLite in-memory — no services needed): signing is verifiable by a destination, backoff schedule + cap, retry→dead-letter, replay recovery, idempotency dedupe, auth + tenant isolation, and Cashier webhook signature verification (valid signature mutates state; tampered is rejected).

About

Webhook delivery infrastructure — HMAC-signed events with retry, backoff, dead-lettering and replay. Laravel · Inertia · React · Horizon · Docker

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors