Skip to content

[quality] websiteUrl's bare-host, unparseable and absent arms have no end-to-end coverage (src/lib/profile-links.mjs) #1053

Description

@hivecommons-hive

Finding

websiteUrl() in src/lib/profile-links.mjs resolves the free-text blog
field of a third-party GitHub profile — copied verbatim into
data/community-people.json by scripts/fetch-community-people.mjs and
committed unedited by the scheduled refresh workflow. It is the one place on
the site that turns untrusted third-party text into an href.

Three of its arms are exercised by unit tests but never by a browser, because
no record in the checked-in data has the shape that reaches them:

51  if (typeof value !== 'string') return null;   // blog absent / not a string
55  const candidate = /^[a-z][a-z0-9+.-]*:/i.test(trimmed)
56    ? trimmed
57    : `https://${trimmed}`;                      // bare host, resolved not concatenated
62  } catch {                                      // parses as a scheme, not as a URL
63    return null;

Every real blog value is either "" or an absolute http(s):// URL, so the
no-scheme arm, the parser rejection and the non-string guard are not merely
untested end to end — against the shipped data they are unreachable. The
no-scheme arm is the one that matters most: it is why
trusted.example@attacker.example resolves to a URL whose authority is the
real host instead of being concatenated into a link whose visible prefix and
real authority disagree.

Evidence and provenance

  • Unit: TZ=UTC node tests/tools/coverage-report.mjs at main 900592b
    (node v26.10.0, run locally 2026-10-04) reports src/lib/profile-links.mjs
    at 100.00% lines / 100.00% regions; tests/profile-links.test.mjs
    covers all three arms directly. This is a unit-covered path.
  • End-to-end: job End-to-end coverage, workflow Validate repository,
    run 37164361552
    attempt 1, revision 900592b; artifact e2e-coverage (id 11289266192),
    report.json; manifest runId 37164361552-1, status: passed,
    sealedAt 2026-10-04T00:19:14Z. It puts the file at 100.00% lines /
    57.14% regions
    , uncovered region lines 11 31 33 51 55 62.
  • Reproduced locally at the same revision: npm run build:e2e:coverage,
    then the full Playwright suite under E2E_COVERAGE=1 (298 passed), rendered
    with tests/tools/e2e-coverage-report.mjs. src files comes out at
    379/469 regions (80.81%) against CI's 379/468 (80.98%), and
    profile-links.mjs is identical in both at 57.14% with the same uncovered
    region lines.

Priority 2 under the coverage-evidence rules: covered by unit tests, not by
end-to-end tests.

Caveat on the meter

The percentage in that report is under active correction — #1035 and #1051
show the region union carrying zero-count spans over lines that demonstrably
ran. The reliable signal for this finding is the covered-region count,
which rises when a branch is genuinely reached, not the ratio.

Recommendation

Give the coverage build the three missing shapes through the existing overlay
mechanism (tests/e2e/fixtures/data/community-people.json, applied by
tests/tools/e2e-data-fixtures.cjs under E2E_COVERAGE=1 only, never by
npm run build:production), and assert each rendered outcome in
tests/e2e/data-fixtures.spec.js:

  • a profile with no blog at all → no Website anchor;
  • a profile whose blog is a bare host → a Website anchor whose href is
    https://<host>/, i.e. resolved rather than concatenated;
  • a profile whose blog opens with a scheme but does not parse → no anchor
    rather than a dead one.

Completion criteria

  • The coverage build carries a profile with an absent blog, one with a bare-host blog, and one with an unparseable blog
  • tests/e2e/data-fixtures.spec.js asserts the rendered outcome of each in a browser
  • The e2e report's covered-region count for src/lib/profile-links.mjs rises
  • npm run build:production is unchanged — the overlay stays out of what the site ships

Priority

  • Impact: medium (the one place untrusted third-party text becomes an href, with its anti-spoofing arm unexercised in a browser)
  • Effort: low

🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 900592b

— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88

Activity

  1. added
    qualityApproved by a Hive merger/owner for auto-merge on green CI
    testingApproved by a Hive merger/owner for auto-merge on green CI
    agent/qualityApproved by a Hive merger/owner for auto-merge on green CI
    hive/covered-by-prHive verified that an open PR references or claims this issue; still actionable until confirmed
    on Oct 4, 2026
  2. added
    blocked-on-reporterPaused until the e2e coverage reporter fix (#1079) lands; may be a phantom gap
    on Oct 5, 2026
  3. added a commit that references this issue on Oct 8, 2026
    0b0f932
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/qualityApproved by a Hive merger/owner for auto-merge on green CIblocked-on-reporterPaused until the e2e coverage reporter fix (#1079) lands; may be a phantom gaphive/covered-by-prHive verified that an open PR references or claims this issue; still actionable until confirmedhive/hosted-available-lke648397-260827-5n31Approved by a Hive merger/owner for auto-merge on green CIqualityApproved by a Hive merger/owner for auto-merge on green CItestingApproved by a Hive merger/owner for auto-merge on green CI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions