Repository navigation
[architect] Duplicated GitHub pagination/same-origin-guard logic across collect-metrics.mjs and collect-launch-metrics.mjs #1372
Description
Architecture Finding
Type: tech-debt/coupling
Affected area: scripts/collect-metrics.mjs, scripts/collect-launch-metrics.mjs, scripts/lib/github.mjs
scripts/lib/github.mjs exists specifically to centralize GitHub auth-header
construction ("so that auth format changes and token wiring only need to
happen in one place", per its own top-of-file comment). Despite that stated
goal, the Link-header pagination helper and its same-origin guard are
duplicated verbatim in two scripts instead of living in that shared module:
scripts/collect-metrics.mjs: localgithubAll(url, headers)+
sameOriginNext(candidate, origin)scripts/collect-launch-metrics.mjs: a second, near-identical
githubAll(url, token)+sameOriginNext(candidate, origin), which also
re-implements theAccept/User-Agent/Authorizationheader object
inline instead of calling the already-exportedmakeGitHubHeaders().
Impact
This is security-sensitive code: the same-origin check exists to stop an
Authorization bearer token from being replayed to a Link rel="next" target
on another host. With two independent copies, a future fix to the guard (or a
change to how the token is attached) can land in one copy and silently miss
the other — exactly the failure mode scripts/lib/github.mjs was introduced
to prevent for header construction. The duplication also means the two
scripts' test suites (tests/collect-metrics.test.mjs,
tests/collect-launch-metrics.test.mjs) each exercise their own private copy
of the same logic rather than one shared, single-sourced implementation.
Recommendation
Extract one shared pagination helper, e.g. githubAllPages(url, headers) in
scripts/lib/github.mjs, taking pre-built headers (consistent with the
existing makeGitHubHeaders/githubFetch signatures) so both call sites
build headers via makeGitHubHeaders() and share one same-origin guard.
-
scripts/lib/github.mjsexports a single pagination helper used by both scripts -
scripts/collect-metrics.mjsandscripts/collect-launch-metrics.mjsno longer define their owngithubAll/sameOriginNext -
scripts/collect-launch-metrics.mjsbuilds headers viamakeGitHubHeaders()instead of an inline object - Existing behavior-level tests in
tests/collect-metrics.test.mjsandtests/collect-launch-metrics.test.mjscontinue to pass unmodified (they assert behavior, not internals)
Filed by architect agent (ACMM L5 — hold-gated mode)
🐝 Hive Agent: architect | Instance: hosted-available-lke648397-260827-5n31 | SHA: f5586b0
— hive: agent=architect backend=copilot model=claude-opus-4-6 copilot=1.0.88
Activity