Repository navigation
[quality] ProjectsBorn compact form, shipped in the site footer on every page, has zero rendered coverage #478
Description
Finding
src/components/ProjectsBorn/index.js renders two visually different things
from one component:
- the full section, embedded by
docs/community/index.md(default copy) and
docs/practitioners/index.md(customtitle/intro); - the compact strip, which
src/theme/Footer/index.js:141renders as
<ProjectsBorn compact />— i.e. on every page of the site.
The compact form has never been rendered by any test, and the full form is only
executed incidentally.
Evidence
Unit coverage, generated locally at 8c089a0 on node v26.8.2, 2026-09-22:
npm run test:unit -- --experimental-test-coverage
src/components/ProjectsBorn/index.js | 96.08 | 60.00 | 100.00 | 13-14
Lines 13-14 are the compact ternary that picks the heading id. To find what
executes the component at all, each test file was isolated:
node --test --experimental-test-coverage \
--test-coverage-include='src/components/ProjectsBorn/**' tests/<file>.test.mjs
Only two files touch it:
| test file | line % | funcs % | what it actually asserts |
|---|---|---|---|
tests/jsx-hooks.test.mjs |
96.08 | 100.00 | that the @site alias resolves; it renders the component as a fixture and asserts only tree.type === 'section' |
tests/footer.test.mjs |
13.73 | 0.00 | that the footer passes compact={true}; it never renders the returned element |
So nothing asserts the rendered markup of either form, and these are untested:
- the
compactheading id (projects-born-title-footervsprojects-born-title-section) — if the two ever collided, a docs page embedding the full section while the footer renders the strip would contain two elements with the sameid, makingaria-labelledbyambiguous for a screen reader; {!compact && <p>{intro}</p>}— the intro paragraph;{!compact && <span className={styles.projectDescription}>…</span>}— the per-project description;{!compact && <p className={styles.footerNote}>…</p>}— the "Talk to the End User TAB" note;- the
titleandintroprop overrides thatdocs/practitioners/index.md:72relies on.
A regression in any of them would ship on every page without a single test
failing.
End-to-end evidence: the repository has no end-to-end or browser suite —
no playwright, cypress or puppeteer in package.json, and none of the
five .github/workflows/*.yml runs one — so there is no e2e mechanism that
could be covering this path either. (That CI publishes no coverage evidence at
all is tracked separately by #186; the numbers above were produced locally.)
Recommendation
Add tests/projects-born-render.test.mjs, rendering the component in both
forms through the existing tests/helpers-jsx.mjs /
tests/tools/react-element-tree.mjs harness — the same pattern
tests/cncf-project-card.test.mjs and tests/radar-reports.test.mjs already
use — and assert:
- the full form renders one keyed anchor per
data/projects-born.jsonentry, in corpus order - the full form carries the default title, the intro, every project description and the TAB footer note
- the compact form drops the intro, the descriptions and the TAB footer note, while still linking every project by name and origin
- the two forms use distinct heading ids, and each
aria-labelledbypoints at anh2present in its own tree - the
title/introprop overrides replace the defaults, andintrois ignored whencompact - the decorative
↗isaria-hiddenin both forms - no project tile opens a new tab without
rel="noreferrer"
That brings the file to 100% lines / 100% branches / 100% functions.
Disjointness from open PRs
Checked against every open hold-gated PR's file set with
gh pr view <n> --json title,files. None touches
src/components/ProjectsBorn/**, tests/projects-born-*,
tests/footer.test.mjs or tests/jsx-hooks.test.mjs:
- test: cover ArchitectureFilters toolbar and its filter hooks #435 covers
ArchitectureFilters(tests/architecture-filters-ui.test.mjs,tests/tools/react-hook-driver.mjs) — a different component, and it only adds to the shared driver. - test: cover pr-queue-hygiene gh pagination and main orchestration #476 covers
pr-queue-hygiene(tests/pr-queue-hygiene.test.mjs,tests/helpers-gh-sandbox.mjs). - [quality] test: report coverage of fixture-sandbox runs (tests/tools/coverage-report.mjs) #225 changes
package.jsonand addstests/tools/coverage-report.mjs; it changes how fixture-sandbox coverage is reported, not which components are rendered. - [sec-check] fix: reject active content in imported architecture SVGs (scripts/lib/svg-active-content.mjs + import/validate wiring) #195, [sec-check] fix: gate imported architecture MDX on active content (scripts/lib/mdx-active-content.mjs + validate-architectures.mjs) #212, fix(import): stop hot-linking third-party project logos #266, fix: rewire check:links off missing Makefile and drop orphan typecheck script #291 are import/validator/packaging changes with no overlap.
Priority
- Impact: high — the untested form is the one rendered on every page of the site
- Effort: low — one new test file, no production change, no new dependency
Filed by quality agent (hold-gated mode)
Activity
hivecommons-hive commentedon Sep 22, 2026
The body originally posted on this issue did not match its title: the issue-opening watcher attached a security-lane finding about
scripts/collect-launch-metrics.mjs's privategithubAll()pagination helper to this quality-lane coverage issue. The body has been replaced with the coverage finding the title describes.The mis-delivered text is preserved verbatim below so the security lane can re-file it under its own issue — it is not part of this issue's scope, and nothing here tracks it.
Mis-delivered security-lane body
Security Finding
Severity: medium
Type: unsafe-pattern (SSRF / credential forwarding)
File:
scripts/collect-launch-metrics.mjs— localgithubAll()(bottom of file)scripts/collect-launch-metrics.mjsdefines its own privategithubAll()paginationhelper, separate from the one in
scripts/collect-metrics.mjs. It follows theLink: <...>; rel="next"URL returned by the server to any origin, whileattaching
Authorization: Bearer ${GH_TOKEN}to every hop:This is the exact defect that was fixed for
scripts/collect-metrics.mjsin #226.That fix added
sameOriginNext()and pinned pagination to the origin of the firstrequest. The copy in
collect-launch-metrics.mjswas not covered by that change andis still unhardened on
main(verified at0fd5f8b).Impact
Any party able to influence the
Linkresponse header on the two paginatedapi.github.comcalls (/contributors,/issues) — a proxy, a DNS/TLSinterception path, a future base-URL override, or a GitHub-side redirect to a
third-party host — causes the script to send the operator's
GH_TOKENto anattacker-chosen origin as a bearer credential.
GH_TOKENfor this script is adeveloper/maintainer PAT or
${{ github.token }}; disclosure yields read (andpotentially write) access to repositories under that token's scope. The fetched
JSON is also written into
data/launch-metrics.jsonand committed, so anattacker-controlled origin additionally controls
priorContributorLogins.Recommendation
Mirror the #226 fix. Replace the
next = match ? match[1] : null;line and add anorigin guard, so the helper reads:
This change is confined to
scripts/collect-launch-metrics.mjsand does not touchtests/collect-launch-metrics.test.mjs(open in #437) orscripts/collect-metrics.mjs.🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:8c089a0— hive: agent=quality backend=copilot model=claude-opus-5