feat: relay webhooks to the desktop apps over a WebSocket #1

Merged
jwarykowski merged 1 commit from feat/relay into main 2026-10-16 00:57:56 +00:00
Owner

The relay, generic like the licence server: a Cloudflare Worker at relay.jwarykowski.dev for the products in PRODUCTS (keybars-pro, shepherd-pro), and the apps' Go client.

  • POST /v1//hooks {provider} makes an address and secret; the app connects to /v1//hooks//connect with its token; deliveries to /h/ are checked by the provider and sent down the socket cut to event, repository, branch and number.
  • Providers are pluggable (a signature check and an event mapping); GitHub first.
  • Nothing stored but each hook's product, provider, secret and token hash; deliveries aren't kept; a hook unused for 90 days deletes itself; 10 new hooks a minute per IP.
  • Go: relay.Product{ID}.Create, Delete, Run, and hooks kept in a private hooks.json.

Tested: Vitest with a fake Durable Object state (15), Go tests against a fake relay, and TestAgainstRelay against wrangler dev (signed workflow_run -> ci.failed). Not deployed yet.

The relay, generic like the licence server: a Cloudflare Worker at relay.jwarykowski.dev for the products in PRODUCTS (keybars-pro, shepherd-pro), and the apps' Go client. - POST /v1/<product>/hooks {provider} makes an address and secret; the app connects to /v1/<product>/hooks/<id>/connect with its token; deliveries to /h/<id> are checked by the provider and sent down the socket cut to event, repository, branch and number. - Providers are pluggable (a signature check and an event mapping); GitHub first. - Nothing stored but each hook's product, provider, secret and token hash; deliveries aren't kept; a hook unused for 90 days deletes itself; 10 new hooks a minute per IP. - Go: relay.Product{ID}.Create, Delete, Run, and hooks kept in a private hooks.json. Tested: Vitest with a fake Durable Object state (15), Go tests against a fake relay, and TestAgainstRelay against wrangler dev (signed workflow_run -> ci.failed). Not deployed yet.
feat: relay webhooks to the desktop apps over a WebSocket
All checks were successful
CI / worker (pull_request) Successful in 40s
CI / go (pull_request) Successful in 1m16s
2d77d6ed8f
A Worker with a Durable Object per hook, serving the products listed in
PRODUCTS (keybars-pro, shepherd-pro). POST /v1/<product>/hooks makes an
address and secret for a provider; the app connects to
/v1/<product>/hooks/<id>/connect with its token; deliveries to /h/<id>
are checked by the provider (GitHub's X-Hub-Signature-256 first), cut
down to event, repository, branch and number, and sent to the connected
app. Nothing else is stored, and a hook nobody connects to for 90 days
deletes itself.

The Go package is the apps' client: Create, Delete and Run, and hooks
kept in a private hooks.json.
jwarykowski deleted branch feat/relay 2026-10-16 00:57:56 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jwarykowski/relay!1
No description provided.