Skip to content

feat(api): add public-safe README status badge with badgeEnabled opt-in (#541) - #753

Merged
JSONbored merged 10 commits into
JSONbored:mainfrom
Crystora:feat/541-public-readme-badge
Jun 17, 2026
Merged

feat(api): add public-safe README status badge with badgeEnabled opt-in (#541)#753
JSONbored merged 10 commits into
JSONbored:mainfrom
Crystora:feat/541-public-readme-badge

Conversation

@Crystora

Copy link
Copy Markdown
Contributor

Summary

  • Add a public, unauthenticated README status badge (feat(api): public-safe README status badge #541): GET /v1/public/repos/:owner/:repo/badge.svg and a shields badge.json endpoint.
  • Serve a HARD-whitelisted, repo-level metric set only — median time-to-merge, % real (non-slop) contributions, and a coarse queue-health level — derived from cached pull-request records. No contributor-level data, reward/trust values, or private scoreability context is ever read or exposed.
  • Gate serving on two conditions: the repo must be installed AND opted in via a new badgeEnabled setting. Any other repo (unknown, uninstalled, or not opted in) returns a benign 404 "unavailable" badge with no metrics. Responses are aggressively cached with stale-while-revalidate, mirroring the existing public stats route.

Closes #541

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked an issue, or this is small enough that the summary explains why an issue is not needed.

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage locally; global coverage stays at or above 97% for lines, statements, functions, and branches (aim for 98%+ branch coverage locally so CI variance does not fail near the threshold)
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

npm run test:ci passes end to end. Coverage (src/**): statements 98.65%, branches 97.05%, functions 97.06%, lines 99.27% (all ≥ 97%); the two new modules src/services/public-repo-quality.ts and src/api/badge.ts are 100% statements/branches, and the new route paths are exercised by integration tests. npm audit reports 0 vulnerabilities. ui:openapi:check reports no drift.

If any required check was skipped, explain why:

  • None. The full npm run test:ci gate was run locally and passed.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed. The badge derives only three coarse, repo-level metrics (counts/enums); no contributor-level, reward, or trust data path exists.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics. All badge text is XML-escaped before rendering, and tests assert the SVG/JSON contain no forbidden public terms.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests. The new routes are intentionally unauthenticated (public badge) and excluded from requiresApiToken; negative paths (not installed / not opted in / unknown repo → 404 "unavailable") are covered by integration tests.
  • API/OpenAPI/MCP behavior is updated and tested where needed. Two new public endpoints added and tested; ui:openapi:check is clean (the curated OpenAPI spec is unchanged, consistent with the existing public stats/subnet routes).
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks. N/A — no UI/frontend changes; the badge serves from live cached repo data.
  • Visible UI changes include a UI Evidence section below with JPG/JPEG or PNG screenshots arranged as organized, captioned, clickable thumbnails. SVG screenshots are not used as review evidence. Review-only screenshots or recordings are not committed to the repository. N/A — this is an API endpoint, not a web/extension UI surface (see UI Evidence note below).
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs. N/A — no docs/changelog changes.

UI Evidence

Not applicable — this is a backend API endpoint, not a web/extension UI surface. The badge is a self-rendered SVG served at GET /v1/public/repos/:owner/:repo/badge.svg; its exact content (label, message, color) is asserted in test/unit/badge.test.ts and the integration tests rather than via screenshots.

Notes

  • Migration: 0037_badge_enabled.sql adds repository_settings.badge_enabled (INTEGER NOT NULL DEFAULT 0) — the next free migration number after 0036.
  • Opt-in setting: badgeEnabled is wired through the settings read/write path so maintainers can toggle it via the existing repository-settings endpoint. It is typed optional on RepositorySettings (always populated by the DB layer; default false) to keep the diff focused and avoid churning unrelated settings fixtures.
  • Public-safety isolation: the queue-health level is computed locally from open-PR volume/staleness (a coarse, public-safe classifier) rather than reused from the internal QueueHealth signal, so no private-derived value reaches this unauthenticated surface.
  • Files changed (10, +501): migrations/0037_badge_enabled.sql, src/services/public-repo-quality.ts, src/api/badge.ts, src/api/routes.ts, src/db/schema.ts, src/db/repositories.ts, src/types.ts, test/unit/public-repo-quality.test.ts, test/unit/badge.test.ts, test/integration/api.test.ts.

@ghost

ghost commented Jun 15, 2026

Copy link
Copy Markdown

Note

Gittensory Gate skipped

PR closed before full evaluation. No late first comment was created.

Signal Result Evidence Action
Gate result ⚠️ Skipped #753 is no longer open. No action.

💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

@ghost ghost added the gittensory:reviewed label Jun 15, 2026
@ghost

ghost commented Jun 15, 2026

Copy link
Copy Markdown

gittensory · advisory review

Reviewed 10 changed file(s) — two independent AI reviewers.

Changed files (10)
  • migrations/0037_badge_enabled.sql
  • src/api/badge.ts
  • src/api/routes.ts
  • src/db/repositories.ts
  • src/db/schema.ts
  • src/services/public-repo-quality.ts
  • src/types.ts
  • test/integration/api.test.ts
  • test/unit/badge.test.ts
  • test/unit/public-repo-quality.test.ts

Suggested action:Safe to merge — both reviewers found no blocking issues.

Reviewer A · gpt-oss-120b — recommends ✅ merge
This PR adds a public‑safe README status badge with opt‑in support, introduces the necessary DB column and migration, implements the badge rendering logic, and wires up new routes with proper caching and authentication bypass. The implementation respects the public/private sanitizer, includes comprehensive unit and integration tests, and updates settings handling accordingly.

Suggestions

  • Add a test that verifies the Cache‑Control header on the JSON badge endpoint (mirroring the SVG test).
  • Document the new badgeEnabled flag in the repository settings API docs for maintainers.
  • Ensure the migration 0037_badge_enabled.sql is included in the production deployment pipeline so existing installations receive the new column.

Worth double-checking

  • The migration must be applied before the new code runs; otherwise existing DBs may lack the badge_enabled column.
  • Default badgeEnabled is false, so existing repos will not expose a badge until explicitly enabled.

Reviewer B · nemotron-3-120b-a12b — recommends ✅ merge
The PR adds a public-safe README status badge feature that displays whitelisted repo-level metrics (real contribution %, median time to merge, queue health) for installed repositories that have opted in via badgeEnabled. The implementation respects the public/private boundary by deriving metrics solely from cached PR data without exposing contributor/private context/trust terms. New endpoints are properly secured with XML escaping and appropriate caching. Tests cover core functionality and boundary conditions.

Suggestions

  • Consider adding a comment in src/api/badge.ts explaining why textWidth uses 6.5px per character (approximation for Verdana-like fonts) to aid future maintenance.
  • In src/services/public-repo-quality.ts, the resolveQueueHealthLevel function uses hardcoded thresholds (e.g., openCount >= 50). While acceptable for a coarse metric, consider making these configurable via environment variables for easier tuning without code changes.
  • The escapeXml function correctly handles XML-significant characters but note that the badge SVG uses double quotes for attribute values; escaping of single quotes (') is unnecessary in this context though harmless.

Worth double-checking

  • Verify that the PublicRepoQuality service cannot accidentally leak private fields through PullRequestRecord (review confirms it only uses state, timestamps, and slopBand).
  • Ensure the new badge endpoints are properly integrated with any global rate limiting or DDoS protection mechanisms (not shown in diff but should be verified in broader system).
  • Confirm that the migration's DEFAULT 0 for badge_enabled aligns with the repository settings default false in TypeScript (it does).

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored JSONbored added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jun 15, 2026
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.76%. Comparing base (83b064c) to head (0d8584b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #753      +/-   ##
==========================================
+ Coverage   96.74%   96.76%   +0.02%     
==========================================
  Files          95       97       +2     
  Lines       13905    13992      +87     
  Branches     5075     5098      +23     
==========================================
+ Hits        13453    13540      +87     
  Misses         86       86              
  Partials      366      366              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Crystora

Copy link
Copy Markdown
Contributor Author

@JSONbored fixed ci errors

@JSONbored JSONbored left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #753 — feat(api): add public-safe README status badge with badgeEnabled opt-in (#541)
Verdict: MERGE
Resolves issue #541: FULLY
CI: Green (lint, test 1/2, workers, ui, security, changes). gittensory neutral.

Highlights:

  • Matches the spec: src/api/badge.ts (self-rendered SVG, no external service) + src/services/public-repo-quality.ts deriving only the three whitelisted metrics (median time-to-merge, % non-slop, coarse queue-health). Hard whitelist; no contributor/reward/trust path.
  • Correct opt-in + install gating: unknown/uninstalled/not-opted-in all return a benign 404 "unavailable" badge. Routes excluded from requiresApiToken (intentionally public), cached with stale-while-revalidate; all text XML-escaped; tests assert no forbidden terms + negative paths + cache headers. Queue-health computed locally for public-safety isolation.

Concerns / required changes:

  • Migration number collision: migrations/0037_badge_enabled.sql collides with PR #755's migrations/0037_gate_outcomes.sql (main at 0036). One must renumber to 0038; coordinate ordering.

Completeness vs issue: Fully satisfies the AC — badge serves only whitelisted metrics for installed+opted-in repos, cached, no private-data path, with whitelist/opt-in/cache/redaction tests. Only blocker is the shared 0037 number with #755.

@JSONbored
JSONbored merged commit 54ed808 into JSONbored:main Jun 17, 2026
17 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

feat(api): public-safe README status badge

2 participants