Verified against main at 715c52e.
Impact
A cold public visit currently performs a quick request and then a full request. With 24 recently active, uncached repositories and a one-page repository list, the quick request makes 2 GitHub REST calls and the full request makes 76: viewer + repository list, 48 per-repository commit/latest-PR calls, 24 workflow calls, and 2 issue-search calls. That is 78 unauthenticated requests for one page load, above GitHub's 60-requests-per-hour unauthenticated allowance; the 76-call full Worker invocation also exceeds the 50 external-subrequest limit on Workers Free.
The per-repository latest-PR half of the detail fan-out populates RepoSummary.latestPullRequest, but no browser production code reads that field. A public dashboard can therefore exhaust quota or fail at the Worker boundary while paying for data it does not render. Supplying GITHUB_PUBLIC_TOKEN raises GitHub's API allowance but does not remove the Workers Free subrequest ceiling.
References: GitHub REST rate limits, Cloudflare Workers limits.
Concrete code references
Acceptance criteria
- A cold public quick-plus-full flow at the default scan depth stays at or below 60 GitHub REST requests total.
- No single public Worker invocation requires more than 50 external subrequests under the same 24-active-repository fixture.
- Remove the unused latest-PR fetch and its contract/cache/test surface unless a real rendered consumer is added; do not leave a compatibility alias or parallel payload shape.
- Preserve recent commits, workflow-failure visibility, the global pull-request and issue feeds, bounded scan behavior, and explicit partial-data warnings.
- If the public default scan depth or payload contract changes, update
README.md and docs/ARCHITECTURE.md in the same change.
Test expectations
- Add a server regression test that counts every upstream call for a cold public quick request followed by a cold public full request with 24 active repositories, asserting both ceilings above.
- Assert that authenticated local/hosted aggregation still returns its supported data.
- Run
npm run test -- --project server, npm run test -- --project web, and npm run check under Node 24.18.0.
Dependencies / order
Land this before the repository-activity cache invalidation issue, because correct invalidation can increase detail refresh traffic and must inherit the reduced request budget.
Non-goals
- Upgrading the Cloudflare account or relying on a higher paid-plan ceiling.
- Shipping any GitHub token to the browser.
- Expanding the dashboard to scan every repository on every request.
- Adding a distributed cache or background queue.
Verified against
mainat715c52e.Impact
A cold public visit currently performs a quick request and then a full request. With 24 recently active, uncached repositories and a one-page repository list, the quick request makes 2 GitHub REST calls and the full request makes 76: viewer + repository list, 48 per-repository commit/latest-PR calls, 24 workflow calls, and 2 issue-search calls. That is 78 unauthenticated requests for one page load, above GitHub's 60-requests-per-hour unauthenticated allowance; the 76-call full Worker invocation also exceeds the 50 external-subrequest limit on Workers Free.
The per-repository latest-PR half of the detail fan-out populates
RepoSummary.latestPullRequest, but no browser production code reads that field. A public dashboard can therefore exhaust quota or fail at the Worker boundary while paying for data it does not render. SupplyingGITHUB_PUBLIC_TOKENraises GitHub's API allowance but does not remove the Workers Free subrequest ceiling.References: GitHub REST rate limits, Cloudflare Workers limits.
Concrete code references
Acceptance criteria
README.mdanddocs/ARCHITECTURE.mdin the same change.Test expectations
npm run test -- --project server,npm run test -- --project web, andnpm run checkunder Node 24.18.0.Dependencies / order
Land this before the repository-activity cache invalidation issue, because correct invalidation can increase detail refresh traffic and must inherit the reduced request budget.
Non-goals