Repository navigation
feat(backend): readiness probes, IPFS pinning, GitHub task verification and live leaderboard - #1398
Merged
joelpeace48-cell merged 2 commits intoSep 26, 2026
Conversation
…on and live leaderboard - /readyz verifies the database, Redis and Soroban RPC with per-check timeouts (RPC is degraded-but-ready unless READINESS_REQUIRE_RPC=true); /healthz reports uptime and RPC state. - IPFS pin service (Pinata) for campaign image, rules, badge and metadata, with de-duplication, retries, an SSRF-safe image fetch, POST/GET /campaigns/:id/ipfs-pins and background pinning. - GitHub webhook listener with HMAC verification that records merged PRs and completed issues, plus a master-key lookup for reward verification. - Live leaderboard gateway on the WebSocket server (snapshot on subscribe, rank-change updates, coalesced and masked); fix the ws 8 server constructor so the gateway can start.
|
@zerroai Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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
Four backend features, one per issue. Details, endpoints and env vars are in
docs/BACKEND_PROBES_IPFS_GITHUB_LEADERBOARD.md.Health check and readiness endpoints with RPC status
/readyz(and/health/ready) now runs the dependency checks in parallel, each under a timeout (READINESS_TIMEOUT_MS, default 2s): the database (SELECT 1), Redis (PING, only when configured) and the Soroban RPC. The response lists each check's status, latency and error.503. The database and Redis are required. The RPC is reported but only required withREADINESS_REQUIRE_RPC=true; otherwise a failure yields"status": "degraded"with200, so an RPC blip does not take every pod out of rotation./healthznow returns uptime and the RPC pool state (cached, no network call);/livezis unchanged. A hanging dependency cannot hang the probe.Automated IPFS metadata pin service
services/ipfsPinService.jspins a campaign's image, rules JSON and badge JSON, then a metadata document linking them byipfs://CID, through Pinata (PINATA_JWT). Pins are content-addressed and de-duplicated per campaign (ipfs_pins), and transient provider errors (network, 429, 5xx) are retried with backoff.POST /campaigns/:id/ipfs-pinsandGET /campaigns/:id/ipfs-pins(API key). New campaigns are also pinned in the background through the durable job queue when the service is configured.httpshosts (no private/internal addresses, no redirects),image/*content and 5 MiB, so campaign data cannot be used to make the server fetch internal URLs. Web3.Storage is not implemented; the provider interface is small (pinJson,pinFile) if you want to add it.GitHub webhook listener for bounty task verification
POST /api/v1/webhooks/githubverifiesX-Hub-Signature-256in constant time over the raw body (mounted beforeexpress.json()), then records a task only when GitHub reports a pull request merged or an issue closed as completed (not_plannedand unmerged closes are ignored). Deliveries are idempotent (github_task_events).pingis answered; other events return202.GET /admin/github-tasksandGET /admin/github-tasks/verify?githubLogin=&repo=&number=&kind=let reward logic confirm a task before crediting. This PR records and exposes verification; it does not itself credit on-chain rewards.Real-time WebSocket gateway for live leaderboard updates
{ "type": "subscribe", "channel": "leaderboard", "campaignId": "42" }, receive aleaderboard_snapshot, thenleaderboard_updatemessages (top 10 plus per-entrychanges:new/up/down/same) whenever awarded points change the ranking. Bursts are coalesced (LEADERBOARD_DEBOUNCE_MS), nothing is sent when the ranking did not change, and wallets are masked.ws8 (new WebSocket.Serveris undefined with the ESM default import). It now uses the namedWebSocketServerexport, which the gateway needs.Also adds migrations 044–045, the new env vars to
backend/.env.example, and a changelog entry.Testing
The tests cover the probe semantics (required vs. optional, timeouts, shutdown) and the wired
/readyz, signature verification and every event type for the webhook (through the real app with a raw body), the pin service with a fake provider and fetch (dedupe, retry, SSRF and size limits, Pinata request shape), and the leaderboard diff/gateway plus an end-to-end run over a real WebSocket connection.I did not get a full local run of the backend suite: several existing test files hang here on network calls and open handles (for example
websocket/live-updates.test.js), before and independent of this change.Closes #1255
Closes #1256
Closes #1251
Closes #1257