Repository navigation
feat(gamification): show API key names on the leaderboard - #12385
Merged
diegosouzapw merged 2 commits intoSep 2, 2026
Merged
diegosouzapw merged 2 commits into
diegosouzapw merged 2 commits into
Conversation
The dashboard leaderboard labels its rows under a "Name" column but only
had the API key id to render, so operators saw `0f3c2a11...` where they
expected the key they created. GET /api/gamification/leaderboard now
attaches each entry's API key display name; the page renders that name
and falls back to the shortened id when the key is unknown or deleted.
Scope and exposure:
- The enrichment is route-local (`withApiKeyNames`). The shared getTopN
helper stays id-only, so the federation leaderboard keeps returning
`{ apiKeyId, score }` to peer servers.
- Names come from a new name-only lookup, `getApiKeyDisplayNames`
(src/lib/db/apiKeys/displayNames.ts), which selects `id, name` and
nothing else — no key, key_hash, key_prefix or policy columns can ride
along with the name.
- Live SSE updates carry scores only; the page merges the names it
already fetched so rows do not flip back to raw ids every 5 seconds.
Tests:
- tests/unit/gamification/leaderboard-route-names.test.ts exercises the
route against a temp SQLite database: names attached, `null` for
orphan ids, only `apiKeyId/name/scope/score/updatedAt` exposed,
getTopN and the federation route still id-only, limit validation
unchanged, and the lookup's blank/unknown-id handling.
- tests/unit/ui/leaderboard-api-key-names.test.tsx renders the page
under jsdom: podium and table show the name, fall back to the short
id, and keep names across an SSE update.
Related to diegosouzapw#2403
Co-authored-by: Leon Marcos <leonaniagomez@gmail.com>
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…pw#12385) The Leaderboard rendered apiKeyId.slice(0, 8)… under a column translated as "name". The route now enriches each entry with the key's display name — route-local, so the shared getTopN helper and the federation leaderboard stay id-only — and the page renders name ?? shortId with the full id in a title attribute. The lookup selects only id and name from api_keys, chunked at 200 ids, with unknown ids and blank names omitted; no key material leaves the DB layer. Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green. Thanks @pacocartones.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
apiKeyId.slice(0, 8)…under a column translated as "name".GET /api/gamification/leaderboardnow enriches each entry with the API key's displayname(route-local, so the sharedgetTopNhelper and the federation leaderboard stay id-only), and the page rendersname ?? shortIdwith the full id in atitleattribute.src/lib/db/apiKeys/displayNames.ts) selects onlyid, namefromapi_keys, chunked at 200 ids; unknown ids and blank names are omitted. No key material leaves the DB layer.Related Issues
Validation
tests/unit/gamification/leaderboard-route-names.test.ts(new, 7 cases),tests/unit/ui/leaderboard-api-key-names.test.tsx(new, 2 cases),tests/unit/gamification/*.test.ts+gamification-display-contract.test.ts(100/100),tests/unit/ui/profile-*.test.tsx+ the new page test (8/8, vitest),npm run typecheck:core0,npm run check:changelog-integrityOK,npm run check:db-rulesOKnpm run lint— repository-wide eslint exit 0 (run with--pass-on-unpruned-suppressions; the literal command reports only pre-existing unused global suppressions on this base)release/v3.8.51; focused checks rerun afterwardMutation: removing the route enrichment fails 2 of 7 route tests; reverting the page to the sliced id fails both page tests.
Tests Added Or Updated
tests/unit/gamification/leaderboard-route-names.test.ts(new): names attached per entry; unknown ids and blank names yieldnull; the response key set is exactlyapiKeyId, name, scope, score, updatedAtwith no key material;getTopNstays name-free;GET /api/gamification/federation/leaderboard(real registered server token) still returns exactly{apiKeyId, score}.tests/unit/ui/leaderboard-api-key-names.test.tsx(new): names rendered when present; short id fallback otherwise.Coverage Notes
src/lib/db/apiKeys/displayNames.tsand the route wrapper are fully covered by the route test; the page label helper by the jsdom test.Reviewer Notes
requireManagementAuth. Federation output is unchanged and asserted.neighborsin the REST response remain id-only because the page does not render them; trivial to enrich later.src/lib/db/apiKeys/helper folder rather than inapiKeys.ts, whose base version is not prettier-clean and would have dragged a whole-file reformat into this PR.