code wiki / _hdl_build / nx_media_health_emit.nx
nx_media_health_emit.nx source
↩ module page · 65 lines · 8019 B
1// nx_media_health_emit.nx -- EMITS the MEDIA HEALTH dashboard (knowledge/staging/media/health.html), served at
2// /library/health. Surfaces the media-liveness sweep (operator 2026-07-04: "systems dont confirm if the media is
3// usable... flag this") so the operator can SEE broken/thumbnail-less media instead of discovering it by accident.
4// Self-sufficient: inline login (POST /api/login -> sessionStorage.nx_sess) then fetch /api/mediahealth (the report
5// nx_movie_probe --sweep writes) -> summary tiles + the issue list (path/verdict/reason). ZERO external loads; NO
6// double-quote chars (single-quote HTML/JS) so the fail-closed emit check passes. license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls.nx"
8const K_MAGIC_131072: i64 = 131072
9
10func ua(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[o + i] = s[i]; i = i + 1 } return o + i }
11
12func mh_build(dst: *u8) -> i64 {
13 var o: i64 = 0
14 o = ua(dst, o, "<!doctype html>\n" as *u8)
15 o = ua(dst, o, "<html><head><meta charset=utf-8><meta name=viewport content='width=device-width,initial-scale=1'><base href='/library/'><title>Media Health</title>\n" as *u8)
16 o = ua(dst, o, "<style>\n" as *u8)
17 o = ua(dst, o, "body{font:15px system-ui,-apple-system,Segoe UI,sans-serif;margin:0;background:#0b1220;color:#e6edf6}\n" as *u8)
18 o = ua(dst, o, "#lg{max-width:330px;margin:12vh auto;padding:0 20px}#lg input{width:100%;padding:10px;margin:.4rem 0;box-sizing:border-box;border:1px solid #28406a;border-radius:7px;background:#0e1a30;color:#e6edf6}\n" as *u8)
19 o = ua(dst, o, "button{padding:9px 14px;border:0;border-radius:8px;background:#e8a534;color:#0b2545;font-weight:700;cursor:pointer}.e{color:#ff8a8a;min-height:1.2em}\n" as *u8)
20 o = ua(dst, o, "#hd{background:#0b2545;padding:12px 14px;display:flex;flex-wrap:wrap;gap:10px;align-items:center;position:sticky;top:0;z-index:5}#hd b{font-size:1.05rem}a.lnk{color:#8ac;text-decoration:none;font-size:.9rem}\n" as *u8)
21 o = ua(dst, o, "#tiles{display:flex;flex-wrap:wrap;gap:12px;padding:14px}.tile{background:#13233f;border-radius:10px;padding:12px 16px;min-width:96px}.tile .v{font-size:1.7rem;font-weight:700}.tile .k{font-size:.78rem;color:#9ab}\n" as *u8)
22 o = ua(dst, o, ".ok .v{color:#7bd88f}.deg .v{color:#e8c04a}.brk .v{color:#ff8a8a}.nt .v{color:#e89a4a}\n" as *u8)
23 o = ua(dst, o, "#note{padding:0 14px;color:#9ab;font-size:.86rem}#msg{padding:6px 14px;color:#9ab;font-size:.86rem;min-height:1em}\n" as *u8)
24 o = ua(dst, o, "table{width:calc(100% - 28px);margin:8px 14px 24px;border-collapse:collapse;font-size:.84rem}th,td{text-align:left;padding:6px 8px;border-bottom:1px solid #22344f;word-break:break-all}th{color:#9ab;font-weight:600}\n" as *u8)
25 o = ua(dst, o, ".bDEGRADED{color:#e8c04a}.bBROKEN{color:#ff8a8a}\n" as *u8)
26 o = ua(dst, o, "</style></head><body>\n" as *u8)
27 o = ua(dst, o, "<div id=lg><h2>⚕ Media Health</h2><p style='color:#9ab;font-size:.9rem'>Sign in with your Nishi Library handle.</p><input id=h placeholder=handle autocomplete=username autofocus><input id=p type=password placeholder=passphrase autocomplete=current-password><button id=b>Sign in</button><p id=le class=e></p></div>\n" as *u8)
28 o = ua(dst, o, "<div id=app hidden><div id=hd><b>⚕ Media Health</b><a class=lnk href='.'>← Library</a><a class=lnk href='manga'>My Manga →</a><button id=refresh>Refresh</button></div><div id=note></div><div id=tiles></div><div id=msg></div><table id=tbl hidden><thead><tr><th>Media with issues</th><th>Verdict</th><th>Reason</th></tr></thead><tbody id=tb></tbody></table></div>\n" as *u8)
29 o = ua(dst, o, "<script>\n" as *u8)
30 o = ua(dst, o, "function T(){try{return sessionStorage.nx_sess||''}catch(_){return ''}}function H(){return {'X-Nishi-Session':T()}}\n" as *u8)
31 o = ua(dst, o, "function tile(color,v,k){return '<div class=tile><div class=v style=color:'+color+'>'+v+'</div><div class=k>'+k+'</div></div>'}\n" as *u8)
32 o = ua(dst, o, "function esc(s){return String(s).replace(/[<&>]/g,function(c){return c==='<'?'<':c==='>'?'>':'&'})}\n" as *u8)
33 o = ua(dst, o, "function load(){var msg=document.getElementById('msg');msg.textContent='Loading report...';fetch('api/mediahealth',{headers:H()}).then(function(r){if(r.status===401||r.status===403){sessionStorage.removeItem('nx_sess');location.reload();return null}if(r.status===404){msg.textContent='No sweep has run yet. Ask the operator to run a media-health sweep.';return null}return r.json()}).then(function(j){if(!j)return;render(j)}).catch(function(){msg.textContent='Could not load the health report.'})}\n" as *u8)
34 o = ua(dst, o, "function render(j){document.getElementById('msg').textContent='';var scope=j.scope||'media';var t=document.getElementById('tiles');t.innerHTML=tile('#7bd88f',(j.ok||0),'OK')+tile('#e8c04a',(j.degraded||0),'Degraded')+tile('#ff8a8a',(j.broken||0),'Broken')+tile('#e89a4a',(j.no_thumbnail||0),'No thumbnail');\n" as *u8)
35 o = ua(dst, o, "var note=document.getElementById('note');var cov='';if(j.swept<j.total){cov=' (sampled '+j.swept+' of '+j.total+' - raise the sweep max to cover all)'}note.innerHTML='Scope: <b>'+esc(scope)+'</b>. Swept '+ (j.swept||0) +' items'+cov+'. Books are verified separately (per-page decode).';\n" as *u8)
36 o = ua(dst, o, "var iss=j.issues||[];var tb=document.getElementById('tb');var tbl=document.getElementById('tbl');if(!iss.length){tbl.hidden=1;note.innerHTML+=' <b style=color:#7bd88f>No issues found in this sweep.</b>';return}tbl.hidden=0;var h='';for(var i=0;i<iss.length;i++){var x=iss[i];h+='<tr><td>'+esc(x.path||'')+'</td><td class=b'+esc(x.verdict||'')+'>'+esc(x.verdict||'')+'</td><td>'+esc(x.reason||'')+'</td></tr>'}tb.innerHTML=h;if(j.issues_capped){note.innerHTML+=' <b>(issue list capped)</b>'}}\n" as *u8)
37 o = ua(dst, o, "function showApp(){document.getElementById('lg').hidden=1;document.getElementById('app').hidden=0;load()}\n" as *u8)
38 o = ua(dst, o, "document.getElementById('refresh').onclick=load;\n" as *u8)
39 o = ua(dst, o, "document.getElementById('b').onclick=function(){document.getElementById('le').textContent='';var b='handle='+encodeURIComponent(document.getElementById('h').value)+'&passphrase='+encodeURIComponent(document.getElementById('p').value);fetch('api/login',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:b}).then(function(r){if(!r.ok)throw 0;return r.json()}).then(function(j){sessionStorage.nx_sess=j.token;showApp()}).catch(function(){document.getElementById('le').textContent='Wrong handle or passphrase.'})};\n" as *u8)
40 o = ua(dst, o, "document.getElementById('p').addEventListener('keydown',function(e){if(e.key==='Enter')document.getElementById('b').click()});\n" as *u8)
41 o = ua(dst, o, "if(sessionStorage.nx_sess){showApp()}\n" as *u8)
42 o = ua(dst, o, "</script></body></html>\n" as *u8)
43 return o
44}
45
46func mh_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
47func mh_w(s: *u8) -> i64 { sys_write(1, s, mh_slen(s)); return 0 }
48
49func main() -> i64 {
50 let buf: *u8 = sys_mmap(K_MAGIC_131072)
51 let n: i64 = mh_build(buf)
52 // fail-closed: refuse a double-quote leak or an external <script src
53 var bad: i64 = 0; var i: i64 = 0
54 while i < n {
55 if buf[i] == (34 as u8) { bad = 1 }
56 if i + 12 <= n { if buf[i]==(60 as u8) { if buf[i+1]==(115 as u8) { if buf[i+2]==(99 as u8) { if buf[i+3]==(114 as u8) { if buf[i+7]==(32 as u8) { if buf[i+8]==(115 as u8) { if buf[i+9]==(114 as u8) { bad = 2 } } } } } } } }
57 i = i + 1
58 }
59 if bad != 0 { mh_w("HEALTH-UI REFUSED (sovereignty check failed)\n" as *u8); sys_exit(1); return 1 }
60 let fd: i64 = sys_openat_wr("knowledge/staging/media/health.html" as *u8, 0x1a4)
61 if fd < 0 { mh_w("HEALTH-UI write-fail\n" as *u8); sys_exit(1); return 1 }
62 sys_write(fd, buf, n); sys_close(fd)
63 mh_w("HEALTH-UI OK knowledge/staging/media/health.html\n" as *u8)
64 sys_exit(0); return 0
65}