Skip to content

api(badge): the README badge routes publish only 200 despite a documented 404 and 503 #9710

Description

@JSONbored

⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.

Context

#8377 gave GET /v1/public/repos/:owner/:repo/badge.svg and .../badge.json route-level error handling. The handlers now distinguish three outcomes deliberately — the route comment at src/api/routes.ts:1452-1459 spells it out: "503, never 404: 404 stays reserved for the real 'no public badge for this repo' case so a monitor can tell the two apart, and the 503 branch uses the SHORT cache so a transient failure is never cached for the long stale-while-revalidate window."

  • badge.svg (:1461-1475): 404 at :1467 (no opted-in badge), 503 at :1472 (loader threw), 200 otherwise.
  • badge.json (:1477-1491): 404 at :1482, 503 at :1489, 200 otherwise.

The spec entries added in #9531 (src/openapi/internal-and-public-route-specs.ts:230-247) declare only 200: "Badge payload" / 200: "SVG badge". The two statuses a monitor is explicitly supposed to be able to tell apart are absent from the published contract, and so is the distinct Cache-Control each branch sets.

These are the most externally-visible routes in the API — they are embedded in third-party READMEs behind GitHub's camo proxy — and the OpenAPI document is what an integrator building a badge monitor reads.

Requirements

  • Add 404 and 503 to both getRepoBadgeSvg and getRepoBadgeJson in src/openapi/internal-and-public-route-specs.ts.
  • The 404 description must say the repo has no public badge (unknown, private, uninstalled, or badgeEnabled off) and the 503 description must say the badge data could not be loaded — matching the distinction the handler comment declares.
  • Do not change any handler behaviour, status, or cache header.
  • Regenerate and commit apps/loopover-ui/public/openapi.json.

⚠️ Required pattern: mirror the sibling public route GET /v1/public/repos/{owner}/{repo}/quality, whose handler (src/api/routes.ts:1495-1506) has the same 404/503 split. It does NOT satisfy this issue to collapse 404 and 503 into one entry; to change the badge handlers to return a single status; or to add the statuses to only one of the two badge routes.

Deliverables

  • In the regenerated apps/loopover-ui/public/openapi.json, GET /v1/public/repos/{owner}/{repo}/badge.svg and GET /v1/public/repos/{owner}/{repo}/badge.json each declare 200, 404, and 503.
  • A new test asserts badge.json answers 404 (not 503) for a repo with no public badge, and that the response carries Cache-Control: public, max-age=300.
  • A new test asserts badge.json answers 503 (not 404) when the loader throws, and that the response carries the same short Cache-Control: public, max-age=300.
  • The equivalent two assertions for badge.svg, including that the body is renderUnavailableBadgeSvg() in both branches.
  • A new assertion that both statuses are declared for both operations in buildOpenApiSpec().
  • apps/loopover-ui/public/openapi.json regenerated and committed.

All Deliverables above are required in a single PR. A PR that satisfies only some of them — for example adding the two statuses to the spec without the tests that pin which branch produces which status — does not resolve this issue.

Test Coverage Requirements

src/api/** and src/openapi/** are inside Codecov's src/** include; the 99% branch-counted patch gate applies. Both arms of the if (!quality) check and both arms of the surrounding try/catch must be covered for each of the two routes — four branches per route. The 404-vs-503 assertions are the named regression tests for this fix.

Expected Outcome

A badge monitor generated from the published document can distinguish "this repo has no public badge" from "the badge service is degraded", which is the exact distinction #8377 built into the handlers.

Links & Resources

src/api/routes.ts:1450-1506; src/openapi/internal-and-public-route-specs.ts:230-247; src/api/badge.ts. Related closed work: #8377.

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions