Skip to content

fix(selfhost): sync brokered self-host installed-repo list from GitHub - #5033

Merged
JSONbored merged 1 commit into
mainfrom
fix/brokered-installed-repo-sync-5028
Jul 11, 2026
Merged

fix(selfhost): sync brokered self-host installed-repo list from GitHub#5033
JSONbored merged 1 commit into
mainfrom
fix/brokered-installed-repo-sync-5028

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • Adds syncBrokeredInstalledRepos (src/orb/installed-repos-sync.ts), an hourly self-host job that fetches a brokered installation's live repo list directly from GitHub (GET /installation/repositories, using the broker-minted token) and upserts repositories.isInstalled accordingly — flipping a repo back to isInstalled: false once GitHub stops returning it.
  • No-op (status: "skipped") outside broker mode (ORB_ENROLLMENT_SECRET unset) — cloud and non-brokered self-host are byte-identical.

Why

Fixes #5028 (part of the isRegistered/isInstalled untangling epic, #5016). The central Orb relay deliberately does not forward installation/installation_repositories webhook events to brokered self-host containers (the container runs under the CENTRAL Orb App, not its own — forwarding those would let it mistake the central app's install state for its own). Without this, a brokered self-host's repositories.isInstalled only populates lazily, the first time a forwarded PR/issue event arrives for a repo — a freshly enrolled, quiet repo has no local row at all, and every core feature this epic is migrating onto isInstalled (signal snapshots, fidelity repair, the open-data backfill, etc.) would silently skip it. This is a prerequisite for the rest of the epic's sub-issues.

Scope

  • Conventional Commit title.
  • Focused — one new sync module, job-type wiring (types/dispatch/cron/queue-classification), tests. No unrelated changes.
  • Follows CONTRIBUTING.md.
  • No linked issue in the Closes #NNNN sense — maintainer PR, not a contributor PR; closes epic sub-issue BLOCKING: Fix isInstalled population for brokered self-host #5028 directly (see Notes).

Validation

  • git diff --check
  • npm run typecheck
  • npm run test:coverage (full, unsharded) — 100% branch coverage on installed-repos-sync.ts; the new db/repositories.ts helper and every wiring point exercised via dedicated + smoke tests.
  • npm run test:ci (full local gate)
  • npm audit --audit-level=moderate — clean
  • New behavior has dedicated unit tests: skip-outside-broker-mode, single/multi-page GitHub pagination, repo-removed self-heal, both fail-safe catch branches (broker exchange failure, GitHub API failure, non-Error rejection), plus a cron-gating test (hourly-only, broker-mode-only) and a dispatcher smoke-test entry.

Safety

  • No secrets/wallets/hotkeys/trust-scores/reward values anywhere. The broker token itself is never logged; only a structured reason string (HTTP status or a bounded error message) surfaces on failure.
  • No auth/cookie/CORS/session changes — reuses the existing broker-token exchange (fetchBrokeredInstallationToken) unmodified.
  • No UI changes.
  • MAINTENANCE_JOB_TYPES and GITHUB_BUDGET_BACKGROUND_TYPES both updated so the new job participates correctly in the self-host maintenance-trickle and GitHub-rate-limit-yielding policies.

Known limitation (flagged, not blocking)

The generic per-message GitHub rate-limit admission check (githubRateLimitAdmissionKeyForJob) can't resolve an installation-scoped key for this job type, because the installationId isn't known until the broker exchange happens at execution time (not at dispatch time). The job is still correctly marked as a GitHub-budget consumer (GITHUB_BUDGET_BACKGROUND_TYPES) for classification/metrics purposes, but doesn't get pre-emptive per-installation admission gating the way repo-scoped jobs do. Given the low call volume (typically 1 request per hour, more only for large installations) and hourly cadence, this is an acceptable gap rather than something to force through a synthetic message field.

Notes

The central Orb relay deliberately does not forward installation/
installation_repositories webhook events to brokered self-host
containers, so a brokered instance only ever learns about a repo the
first time a forwarded PR/issue event arrives for it -- a freshly
enrolled, quiet repo has no local repositories row at all. Add an
hourly, broker-mode-only sync that fetches the live installation repo
list directly via the broker token (GET /installation/repositories)
and keeps isInstalled in sync, including flipping a removed repo back
to false. No-op everywhere else (cloud, non-brokered self-host).

Fixes #5028, part of the isRegistered/isInstalled untangling epic (#5016).
@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.36%. Comparing base (dcc1601) to head (75e1748).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5033   +/-   ##
=======================================
  Coverage   94.36%   94.36%           
=======================================
  Files         458      459    +1     
  Lines       39255    39285   +30     
  Branches    14322    14329    +7     
=======================================
+ Hits        37042    37072   +30     
  Misses       1558     1558           
  Partials      655      655           
Flag Coverage Δ
shard-1 46.44% <16.66%> (-0.31%) ⬇️
shard-2 33.63% <6.66%> (+0.24%) ⬆️
shard-3 31.35% <6.66%> (-0.12%) ⬇️
shard-4 32.58% <90.00%> (-0.22%) ⬇️
shard-5 34.34% <6.66%> (+0.87%) ⬆️
shard-6 45.42% <10.00%> (+0.28%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/db/repositories.ts 96.73% <100.00%> (+<0.01%) ⬆️
src/index.ts 95.50% <100.00%> (+0.05%) ⬆️
src/orb/installed-repos-sync.ts 100.00% <100.00%> (ø)
src/queue/job-dispatch.ts 100.00% <100.00%> (ø)
src/selfhost/maintenance-admission.ts 100.00% <ø> (ø)
src/selfhost/queue-common.ts 95.69% <ø> (ø)
src/types.ts 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored JSONbored self-assigned this Jul 11, 2026
@JSONbored
JSONbored merged commit 5b2334e into main Jul 11, 2026
18 checks passed
@JSONbored
JSONbored deleted the fix/brokered-installed-repo-sync-5028 branch July 11, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

BLOCKING: Fix isInstalled population for brokered self-host

1 participant