A small static dashboard that lists "sources", their "claims", and "proofs" by calling the Source Score API.
The app is intentionally lightweight: plain HTML, a shared browser auth helper, and a small Node-based test script for the auth helper.
index.html— Sources: fetchesGET /sourcesand shows each source's name, score, URL, and tags. Click a source to openclaims.html?source={digest}. The selected source name is saved tosessionStorageassourceName.claims.html— Claims: reads?source=<digest>, fetchesGET /source/{sourceUriDigest}/claims, and lists claim titles, URLs, checked status, and validity. Clicking a claim opensproofs.html?claim={digest}and storesclaimNameinsessionStoragefor the header.proofs.html— Proofs: reads?claim=<digest>, fetchesGET /claim/{claimUriDigest}/proofs, and shows whether the proof supports the claim, the proof URL, and who reviewed it.auth.js— Shared helper exposed aswindow.SourceScoreAuthin the browser. It fetches, caches, expires, and applies JWT auth headers.tests/run.js— Node smoke tests for JWT payload parsing and token expiry parsing.
- Use the table links to move from
index.html→claims.html→proofs.html. - Each link passes a SHA-256 hex digest as a query parameter (e.g.
?source=<digest>or?claim=<digest>). The UI usesencodeURIComponent()when building these URLs. - A Back button on
claims.htmlandproofs.htmlcallshistory.back()to return to the previous page. claims.htmlandproofs.htmlshow placeholder rows when required query parameters are missing.
- Base URL:
https://source-score.onrender.com/api/v1 - Auth URL:
https://source-score.onrender.com/auth/token - Endpoints used by this UI:
GET /sourcesGET /source/{sourceUriDigest}/claimsGET /claim/{claimUriDigest}/proofs
- Headers:
Client-ID: web-dashboardAuthorization: Bearer <jwt>
- The UI fetches a JWT with
POST /auth/token, caches it inlocalStorageundersourceScoreJwtToken, and invalidates it when the decoded token expiry time is reached. auth.jsaccepts common expiry payload fields (exp,ExpiresAt,expiresAt, andexpires_at) as numeric seconds, numeric milliseconds, numeric strings, or parseable date strings.- The token request uses
AbortSignal.timeout(90000)so auth calls do not hang indefinitely in supported browsers.
Start a static server from the repository root:
python3 -m http.server 8000Then open http://localhost:8000/.
Do not rely on opening the HTML files directly from disk; the shared auth.js script and remote API calls are best exercised through a local server.
Run the auth helper tests with:
npm testManual smoke test:
- Open
http://localhost:8000/. - Confirm sources load.
- Click a source to open claims.
- Click a claim to open proofs.
- All user-facing data is escaped with an
escapeHtml()helper to reduce XSS risk. - Shared Source Score auth code lives in
auth.jsand is exposed aswindow.SourceScoreAuth. auth.jsalso exportsparseJwtPayloadandgetTokenExpiresAtunder CommonJS for the Node test runner.- Path components that contain digests are URL-encoded with
encodeURIComponent(). - The UI uses a short refresh interval (
REFRESH_MS = 5000) to poll the API for updates.