feat(orb): add a typed config-push write path to the relay pipeline#7611
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7611 +/- ##
=======================================
Coverage 88.50% 88.51%
=======================================
Files 724 724
Lines 75961 75992 +31
Branches 22612 22617 +5
=======================================
+ Hits 67232 67263 +31
Misses 7681 7681
Partials 1048 1048
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-21 04:12:16 UTC
Review summary Blockers
Nits — 5 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
Adds a discriminator column (kind, default 'github_webhook') to
orb_relay_pending so the pull-drain loop can eventually tell an
operator-addressed config-push notice apart from a GitHub webhook row
(dispatch side is a separate follow-up). A new POST /v1/app/fleet/config-push
endpoint lets an operator enqueue a typed { pushId, message, capability?,
deprecatesAt? } payload for an explicit list of installation_ids, mirroring
the kill-switch endpoint's requireAppRole + zod-validated-body pattern.
Placed under /v1/app/*, not /v1/internal/* (the latter's own middleware
requires a bearer INTERNAL_JOB_TOKEN and never resolves a session identity
for it, which would make requireAppRole's session-role branch unreachable
for a control-panel caller -- see the route's own doc comment).
Write side only: enqueueConfigPushRelay shares the same TTL pruning and
per-installation backlog cap as the existing webhook path, but skips its
GitHubWebhookPayload-shaped coalesce-key derivation entirely (a config_push
payload never has that shape). No existing webhook-row behavior changes.
Closes #7522
…-webhook queue (#7615) * feat(orb): dispatch config_push relay rows separately from the GitHub-webhook queue drainOrbRelayWithMonitor's per-event loop now branches on kind BEFORE calling args.enqueue (which unconditionally does JSON.parse(rawBody) as GitHubWebhookPayload): a 'config_push' row routes to a new dedicated handleConfigPushRelayEvent (receive-and-log only, per #4902's v1 scope -- no capability-toggle or config-mutation side effect implemented here). Everything else -- 'github_webhook' and any old-shaped/missing kind -- falls through to the existing path unchanged. Threads `kind` through the read side that feeds the drain loop: pullRelayPending's SELECT + RelayPendingEvent, the /v1/orb/relay/pull response (no code change needed there -- it just returns pullRelayPending's output), and drainOrbRelay's HTTP response parsing (defaults a missing `kind` to 'github_webhook' for a rolling deploy against an older Orb server). Closes #7523 * chore(orb): register the config_push relay metric selfhost-metrics.test.ts scans every incr() call site for its metric name and cross-checks it against DEFAULT_METRIC_META -- loopover_orb_config_push_received_total (introduced in the previous commit) was missing. * test(selfhost): cover the non-Error branch of the config_push throw log Closes the codecov/patch gap on PR #7615 -- handleConfigPushRelayEvent's error-logging ternary (error instanceof Error ? error.message : String(error)) only had its Error-instance arm exercised.
…t per target enqueueConfigPushRelay pruned the shared orb_relay_pending table on every call, but the route fans it out over up to 500 installationIds via Promise.all -- turning one request into up to 500 redundant global TTL-prune scans/deletes. Moves the prune to the route handler, called once before the fan-out; enqueueConfigPushRelay no longer prunes itself.
4fe99ca to
5d0e650
Compare
Summary
kinddiscriminator column (default'github_webhook') toorb_relay_pending, migration0168_orb_relay_pending_kind.sql— every existing/future webhook row is untouched.enqueueConfigPushRelay(src/orb/relay.ts) writes an operator-addressedconfig_pushpayload ({ pushId, message, capability?, deprecatesAt? }) into the same queue the webhook relay uses, sharing its TTL pruning and per-installation backlog cap but skipping the webhook-only coalesce-key derivation entirely.POST /v1/app/fleet/config-pushendpoint, gated viarequireAppRole(c, ["operator"])and a.strict()zod body schema, mirroring the kill-switch endpoint's exact auth/validation pattern. Accepts an explicitinstallationIdslist (no percentage/canary selector — none exists in this codebase to build on) and enqueues one row per target, audited asoperator.config_push_enqueued.Placed under
/v1/app/*rather than the issue's illustrative/v1/internal/*example path — that prefix's own middleware requires a bearerINTERNAL_JOB_TOKENand (perrequiresApiToken's explicit/v1/internal/exclusion) never resolves a session identity there at all, which would makerequireAppRole's session-role branch unreachable dead code for a control-panel caller./v1/app/*is where that pattern is actually meaningful, matching the kill-switch endpoint's own placement (a bearer token caller still passesrequireAppRole's non-session branch either way).Write side only, per the issue's explicit scope: does not touch
enqueueWebhookByEnvordrainOrbRelayWithMonitor— the dispatch/read side is the companion issue #7523.Test plan
npm run typechecknpm run db:migrations:check/npm run db:schema-drift:checknpm run ui:openapi:check(no surface change — internal-only route, not documented, matching the kill-switch endpoint's own precedent)test/unit/routes-config-push.test.ts: multi-target enqueue, idempotency per(pushId, installation), a pre-existing webhook row'skindstays'github_webhook'untouched, 400 on schema-invalid/malformed body, 403/401 auth matrix (non-operator session, no identity, shared MCP token), operator-session success + audit roworigin/main)local-branch.test.ts'sdefaultBaseReftest andminer-attempt-worktree.test.ts's real-git-subprocess test — both reproducibly pass in isolation; resource-contention flakes under full-parallel load, confirmed unrelated to this diff)Closes #7522