Closes #15
/claim 15
What this builds
Full implementation of the Community & User Reputation system: structured peer reviews, inline comments,
CRediT contributor credits, transparent reputation scoring, leaderboards, and badges — as a self-contained
community-reputation/ module.
How to run the demo
Only Docker Desktop required — no Node.js needed:
./community-reputation/dev.sh –demo –docker
With Node.js ≥ 18:
./community-reputation/dev.sh –demo
Opens at http://localhost:3000. A Demo login bar appears at the top — click Alice Chen ★ to sign in as the
admin user and try posting reviews, comments, and endorsements from the UI.
Quick API smoke-test
curl -s ‘http://localhost:3000/api/leaderboards’ | jq .
curl -s ‘http://localhost:3000/api/leaderboards?domain=biology’ | jq .
curl -s ‘http://localhost:3000/api/reviews?projectId=demo-project-alice’ | jq .
What’s included
14 API routes covering the full spec:
- POST/GET /api/reviews — Zod-validated, auth-gated, self-review rejected at the service layer
- GET/PATCH/DELETE /api/reviews/:id — visibility enforced on every read path
- POST/GET /api/comments — polymorphic targets (review, project, document, dataset, code block, notebook
cell), threaded replies
- DELETE /api/comments/:id — soft-delete, author only
- POST/GET /api/contributions — full 14-role CRediT taxonomy
- GET /api/contributions/export — CSV download for tenure/promotion portfolios
- DELETE /api/contributions/:id — soft-delete
- POST/DELETE/GET /api/endorsements — rate-limited to 10/day, self-endorse rejected with 422
- GET /api/reputation/:userId — live score with full per-component breakdown
- GET /api/reputation/:userId/history — append-only snapshot history for sparklines
- GET /api/leaderboards — domain / region / institution filters using a LATERAL JOIN
- GET /api/users/:userId/badges — earned badges with metadata
- GET /api/cron/reputation-snapshots — Vercel Cron compatible, protected by secret header
Reputation engine — composite score using log1p smoothing per component to prevent power-user dominance.
Weights sum to 100 for easy auditing. Every API response includes a breakdown array so scores are fully
explainable.
Visibility enforcement — serializeReview() in src/lib/visibility.ts is the single enforcement point for all
four modes (PUBLIC / SEMI_PRIVATE / ANONYMOUS / DOUBLE_BLIND) across every read path.
UI pages:
- /leaderboard — ranked table with live domain, region, and institution filters
- /users/:userId — reputation breakdown, badges, endorsements grouped by skill, CRediT contributions with CSV
export link
- /projects/:projectId — CRediT contributor graph, peer reviews with star ratings, inline review submission
form, threaded comment panel per review
Tests & CI — 46 tests total: 25 unit (reputation scorer, visibility rules, badge thresholds) and 21
integration (anonymity enforcement, endorsement guards, leaderboard ordering, review lifecycle, soft-delete
behaviour). GitHub Actions CI runs typecheck + unit + integration with a Postgres service container on every
push and PR.
Known limitations (documented in README)
- citationsReceived, forksReceived, and bountiesCompleted stub at 0 — these require external data sources (DOI
registry, project fork counter, BountyCompletion table) that are out of scope for this issue
- List endpoints return all matching rows — cursor pagination is a follow-up
- GitHub OAuth requires real credentials for production; the dev environment uses a local-only credentials
bypass for one-click demo login
Demo
https://github.com/user-attachments/assets/ad75cb80-a9f2-4cb4-8bc2-8e73a54b3418