de7e5ec landed leaderboard_routes.py + the route file's register fn but
the import + register_leaderboard_routes(app) call + auth-middleware
allowlist were never added to app.py — endpoint returned 404 in production.
Three minimal edits to app.py mirror the existing register_*_routes pattern
(import at line 28, allowlist OR-clause at line 512, register call at 2365).
Plus a SQL bug in _parse_window: rolling-window clauses prefixed "AND "
but the WHERE composition uses " AND ".join(...), producing
"WHERE 1=1 AND AND ce.timestamp..." → sqlite3.OperationalError on every
window=Nd / window=Nh request. Stripped the prefix and added a comment so
the asymmetry doesn't bite again.
Verified on VPS:
GET /api/leaderboard?window=all_time&kind=person → 200, 11 rows
GET /api/leaderboard?window=7d&kind=person → 200, 2 rows
GET /api/leaderboard?window=30d&kind=person → 200, 9 rows
GET /api/leaderboard?domain=internet-finance → 200, 3 rows
GET /api/leaderboard?kind=agent → 200, leo/rio/clay/astra/vida
Unblocks: Argus dashboard cutover, Oberon column reorder, Leo's CI
taxonomy broadcast.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New endpoint replaces the legacy /api/contributors *_count read path with
event-sourced reads from the Phase A contribution_events ledger.
- Params: window (all_time | Nd | Nh), kind (person | agent | org | all),
domain (filter), limit (default 100, max 500)
- Returns per-handle CI, full role breakdown (author/challenger/synthesizer/
originator/evaluator), events_count, pr_count, first/last contribution
- ORDER BY ci DESC, last_contribution DESC — recent contributors break ties
- Read-only sqlite URI; total/has_more computed for paginated UIs
Wiring (import + register + _PUBLIC_PATHS entry) currently applied to live
app.py on VPS only — repo app.py has drift from Ship's uncommitted /api/search
POST contract. Next deploy.sh round-trip needs both to land together.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>