Skip to content

feat(orb): central Orb App webhook receiver (POST /v1/orb/webhook) - #1293

Merged
JSONbored merged 1 commit into
mainfrom
feat/orb-webhook-receiver
Jun 25, 2026
Merged

feat(orb): central Orb App webhook receiver (POST /v1/orb/webhook)#1293
JSONbored merged 1 commit into
mainfrom
feat/orb-webhook-receiver

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

The first piece of the central Gittensory Orb GitHub App (#1255) — the one shared app maintainers install (the das-github-mirror model). GitHub delivers its install + PR/review events to POST /v1/orb/webhook on gittensory-api; this is the data spine for the homepage fleet metrics (reviews initiated / merged / closed / reversals).

It ports the proven src/github/webhook.ts handler verbatim — only the secret and the dedup table differ:

  • Verifies the Orb App's own webhook secret (ORB_GITHUB_WEBHOOK_SECRET, distinct from the review app's GITHUB_WEBHOOK_SECRET). Absent secret → fail-closed 401, so the route is inert until the secret is injected (wrangler secret put).
  • Its own orb_webhook_events dedup table (migration 0063) — a GitHub delivery_id is only unique per App, so it can't safely share webhook_events with the review app.
  • Body-size cap, signature verification, dedup, and identical 202/400/401/413 responses. Exempt from requiresApiToken; strict rate-limit class (same as /v1/github/webhook).

Receive + verify + record only — install-registry and PR-outcome processing land in follow-up PRs (#2#7 of the Orb-app sequence). Purely additive: the live /v1/orb/ingest collector, orb_signals, and fleet analytics are untouched. The endpoint must exist now because GitHub starts POSTing install/ping deliveries the moment the Orb App is created.

Scope

  • 6 files; migration 0063_orb_webhook_events.sql is the next contiguous number
  • Additive only — no existing route/path/table behavior changed; new env binding is optional + fail-closed

Validation

  • npm run test:ci — green (db:migrations:check, typecheck, coverage, workers, ui)
  • 100% branch coverage on src/orb/webhook.ts (15 cases: missing headers, absent/invalid signature, content-length vs streamed 413, non-JSON, install-event extraction, null-field payloads, redelivery dedup, changed-payload re-record, processed/error status handling, empty-body, undefined-chunk, non-numeric content-length)

Safety

  • Fail-closed: no secret / bad signature → 401; never trusts an unverified payload
  • Own dedup table avoids cross-App delivery_id collision with the review app

Deploy note

After merge + auto-deploy, inject the secret: wrangler secret put ORB_GITHUB_WEBHOOK_SECRET (the value you set in the Orb App's webhook config). Until then every delivery returns 401 — no crash, no data loss.

Advances #1255.

@dosubot dosubot Bot added the size:L label Jun 25, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.09%. Comparing base (a3edd8e) to head (2f6f189).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1293      +/-   ##
==========================================
+ Coverage   95.07%   95.09%   +0.01%     
==========================================
  Files         178      179       +1     
  Lines       20039    20092      +53     
  Branches     7206     7228      +22     
==========================================
+ Hits        19053    19106      +53     
  Misses        395      395              
  Partials      591      591              
Files with missing lines Coverage Δ
src/api/routes.ts 94.44% <100.00%> (+<0.01%) ⬆️
src/auth/rate-limit.ts 98.76% <100.00%> (+0.01%) ⬆️
src/orb/webhook.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

First piece of the central Gittensory Orb GitHub App (#1255) — the ONE shared app
maintainers install (das-github-mirror model). GitHub delivers its install + PR/review
events here, to gittensory-api; this is the data spine for the homepage fleet metrics
(reviews initiated / merged / closed / reversals).

Ports the proven src/github/webhook.ts handler verbatim — only the secret and the dedup
table differ:
- Verifies the Orb App's OWN webhook secret (ORB_GITHUB_WEBHOOK_SECRET, distinct from the
  review app's GITHUB_WEBHOOK_SECRET; absent → fail-closed 401, so the route is inert until
  the secret is injected).
- Its own orb_webhook_events dedup table (migration 0063) — a GitHub delivery_id is only
  unique per App, so it can't share webhook_events with the review app.
- Body-size cap, signature verification, dedup, and 202/400/401/413 responses identical to
  the review-app handler. Exempt from requiresApiToken; strict rate-limit class.

Receive + verify + record only — install-registry and PR-outcome processing land in
follow-up PRs. Purely additive; the live /v1/orb/ingest collector is untouched.

Advances #1255.
JSONbored added a commit that referenced this pull request Jun 25, 2026
Second piece of the central Gittensory Orb GitHub App (#1255). Maintains
orb_github_installations (migration 0064) from the verified /v1/orb/webhook
`installation` lifecycle events — one row per install of the shared Orb App, recording
account + repository_selection and the suspend/unsuspend/deleted lifecycle. This is the
registry onboarding + the token-broker (later PRs) read to know which installations
exist and who owns them.

- registered=0 by default — the Mirror-style manual-onboarding gate (an install is
  RECORDED but not trusted/active until a human opts it in), mirroring #1274.
- The upsert runs synchronously in the receiver, BEFORE recording the webhook event, so a
  failed registry write is flipped to "error" + 500 and GitHub redelivers (the dedup guard
  only suppresses non-error rows). No-op for every non-installation event.

Additive; stacked on #1293 (the webhook receiver). installation_repositories repo-delta
tracking and PR-outcome processing are follow-ups.

Advances #1255.
@JSONbored
JSONbored force-pushed the feat/orb-webhook-receiver branch from 2a72c81 to 2f6f189 Compare June 25, 2026 02:04
JSONbored added a commit that referenced this pull request Jun 25, 2026
Second piece of the central Gittensory Orb GitHub App (#1255). Maintains
orb_github_installations (migration 0064) from the verified /v1/orb/webhook
`installation` lifecycle events — one row per install of the shared Orb App, recording
account + repository_selection and the suspend/unsuspend/deleted lifecycle. This is the
registry onboarding + the token-broker (later PRs) read to know which installations
exist and who owns them.

- registered=0 by default — the Mirror-style manual-onboarding gate (an install is
  RECORDED but not trusted/active until a human opts it in), mirroring #1274.
- The upsert runs synchronously in the receiver, BEFORE recording the webhook event, so a
  failed registry write is flipped to "error" + 500 and GitHub redelivers (the dedup guard
  only suppresses non-error rows). No-op for every non-installation event.

Additive; stacked on #1293 (the webhook receiver). installation_repositories repo-delta
tracking and PR-outcome processing are follow-ups.

Advances #1255.
@JSONbored
JSONbored merged commit 513d50b into main Jun 25, 2026
19 checks passed
@JSONbored
JSONbored deleted the feat/orb-webhook-receiver branch June 25, 2026 02:24
JSONbored added a commit that referenced this pull request Jun 25, 2026
Second piece of the central Gittensory Orb GitHub App (#1255). Maintains
orb_github_installations (migration 0064) from the verified /v1/orb/webhook
`installation` lifecycle events — one row per install of the shared Orb App, recording
account + repository_selection and the suspend/unsuspend/deleted lifecycle. This is the
registry onboarding + the token-broker (later PRs) read to know which installations
exist and who owns them.

- registered=0 by default — the Mirror-style manual-onboarding gate (an install is
  RECORDED but not trusted/active until a human opts it in), mirroring #1274.
- The upsert runs synchronously in the receiver, BEFORE recording the webhook event, so a
  failed registry write is flipped to "error" + 500 and GitHub redelivers (the dedup guard
  only suppresses non-error rows). No-op for every non-installation event.

Additive; stacked on #1293 (the webhook receiver). installation_repositories repo-delta
tracking and PR-outcome processing are follow-ups.

Advances #1255.
JSONbored added a commit that referenced this pull request Jun 25, 2026
…1300)

#1293 (orb webhook receiver) and the re-gate sweep PR both grabbed migration number 0063, so main
shipped a duplicate 0063_*.sql and db:migrations:check fails for every branch off main. Renumber the
newest (orb_webhook_events, which uses CREATE TABLE/INDEX IF NOT EXISTS and is not yet deployed) to the
next free number; the sweep marker keeps 0063.
JSONbored added a commit that referenced this pull request Jun 25, 2026
Second piece of the central Gittensory Orb GitHub App (#1255). Maintains
orb_github_installations (migration 0064) from the verified /v1/orb/webhook
`installation` lifecycle events — one row per install of the shared Orb App, recording
account + repository_selection and the suspend/unsuspend/deleted lifecycle. This is the
registry onboarding + the token-broker (later PRs) read to know which installations
exist and who owns them.

- registered=0 by default — the Mirror-style manual-onboarding gate (an install is
  RECORDED but not trusted/active until a human opts it in), mirroring #1274.
- The upsert runs synchronously in the receiver, BEFORE recording the webhook event, so a
  failed registry write is flipped to "error" + 500 and GitHub redelivers (the dedup guard
  only suppresses non-error rows). No-op for every non-installation event.

Additive; stacked on #1293 (the webhook receiver). installation_repositories repo-delta
tracking and PR-outcome processing are follow-ups.

Advances #1255.
JSONbored added a commit that referenced this pull request Jun 25, 2026
Second piece of the central Gittensory Orb GitHub App (#1255). Maintains
orb_github_installations (migration 0064) from the verified /v1/orb/webhook
`installation` lifecycle events — one row per install of the shared Orb App, recording
account + repository_selection and the suspend/unsuspend/deleted lifecycle. This is the
registry onboarding + the token-broker (later PRs) read to know which installations
exist and who owns them.

- registered=0 by default — the Mirror-style manual-onboarding gate (an install is
  RECORDED but not trusted/active until a human opts it in), mirroring #1274.
- The upsert runs synchronously in the receiver, BEFORE recording the webhook event, so a
  failed registry write is flipped to "error" + 500 and GitHub redelivers (the dedup guard
  only suppresses non-error rows). No-op for every non-installation event.

Additive; stacked on #1293 (the webhook receiver). installation_repositories repo-delta
tracking and PR-outcome processing are follow-ups.

Advances #1255.
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.

GitHub App identity unification + atomic webhook-secret swap (retire reviewwed[bot])

1 participant