Sunstead trust scoring project
1<!doctype html>
2<html lang="en">
3<head>
4<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
5<title>Dashboard · Tangled trust</title>
6<style>
7 body { font:14px/1.5 system-ui,sans-serif; margin:0; background:#f6f8fa; color:#1f2328; }
8 header { padding:16px 24px; background:#fff; border-bottom:1px solid #d0d7de; }
9 h1 { margin:0; font-size:18px; } nav a { margin-right:14px; color:#0969da; text-decoration:none; }
10 main { max-width:1000px; margin:24px auto; padding:0 24px; display:grid; gap:16px; grid-template-columns:1fr 1fr; }
11 .card { background:#fff; border:1px solid #d0d7de; border-radius:8px; padding:16px; }
12 .card.wide { grid-column:1/3; } h2 { font-size:13px; text-transform:uppercase; color:#656d76; margin:0 0 12px; }
13 .big { font-size:32px; font-weight:700; } .sub { color:#656d76; }
14 .bars { display:flex; align-items:flex-end; gap:4px; height:120px; }
15 .bar { flex:1; background:#0969da; border-radius:3px 3px 0 0; min-height:2px; }
16 .bar span { display:block; text-align:center; font-size:10px; color:#656d76; margin-top:4px; }
17 .kv { display:flex; justify-content:space-between; padding:4px 0; border-bottom:1px solid #eaeef2; }
18</style>
19</head>
20<body>
21<header>
22 <a href="/" style="display:block;margin-bottom:8px"><img src="/static/logo.svg" alt="CyberCred" height="24"></a>
23 <h1>Observability dashboard</h1>
24 <nav><a href="/">Triage</a><a href="/dashboard">Dashboard</a><a href="/leaderboard.html">Leaderboard</a><a href="/graph.html">Graph</a></nav>
25</header>
26<main id="main">loading…</main>
27<script>
28fetch("/metrics").then(r=>r.json()).then(m=>{
29 const maxd = Math.max(1,...m.score_distribution);
30 const bars = m.score_distribution.map((c,i)=>
31 `<div style="flex:1"><div class="bar" style="height:${100*c/maxd}%" title="${c}"></div>
32 <span>.${i}</span></div>`).join("");
33 const fa = m.false_approval_rate==null ? "n/a" : (m.false_approval_rate*100).toFixed(1)+"%";
34 main.innerHTML = `
35 <div class="card wide"><h2>Trust-score distribution</h2><div class="bars">${bars}</div></div>
36 <div class="card"><h2>Fast-lane rate</h2><div class="big">${(m.fast_lane_rate*100).toFixed(0)}%</div>
37 <div class="sub">${m.decisions.fast_lane} of ${Object.values(m.decisions).reduce((a,b)=>a+b)} contributors</div></div>
38 <div class="card"><h2>False-approval (backtest)</h2><div class="big">${fa}</div>
39 <div class="sub">fast-lane-eligible PRs that were not clean merges</div></div>
40 <div class="card"><h2>Vouch graph</h2>
41 <div class="kv"><span>contributors</span><b>${m.vouch_graph.contributors}</b></div>
42 <div class="kv"><span>edges</span><b>${m.vouch_graph.edges}</b></div>
43 <div class="kv"><span>seed maintainers</span><b>${m.vouch_graph.seeds}</b></div></div>
44 <div class="card"><h2>Decisions</h2>
45 <div class="kv"><span>fast-lane</span><b>${m.decisions.fast_lane}</b></div>
46 <div class="kv"><span>normal queue</span><b>${m.decisions.normal_queue}</b></div>
47 <div class="kv"><span>needs human</span><b>${m.decisions.needs_human}</b></div></div>`;
48});
49</script>
50</body>
51</html>