// /admin — password gate + unconstrained viewer. // // Validates the submitted password against the central server's // ADMIN_PASSWORD env var via POST /api/v1/admin/check, then renders the // real D3 viewer with no URL params (no entity focus, no hop cap). // // Session is stored in sessionStorage so a refresh keeps you in — but // it dies when the tab closes. This is a UX gate, not a security // boundary: the underlying viewer URL is itself public. Real // admin endpoints stay behind the API-key gate on central. const ADMIN_SESSION_KEY = 'graphite_admin_session'; window.Admin = function Admin({ navigate }) { const [authed, setAuthed] = React.useState( () => sessionStorage.getItem(ADMIN_SESSION_KEY) === '1' ); function signOut() { sessionStorage.removeItem(ADMIN_SESSION_KEY); setAuthed(false); } if (!authed) { return { sessionStorage.setItem(ADMIN_SESSION_KEY, '1'); setAuthed(true); }} navigate={navigate} />; } return ; }; function AdminLogin({ onAuth, navigate }) { const [password, setPassword] = React.useState(''); const [busy, setBusy] = React.useState(false); const [error, setError] = React.useState(null); async function submit(e) { e.preventDefault(); setBusy(true); setError(null); const ok = await window.api.adminCheck(password); setBusy(false); if (ok) { onAuth(); } else { setError('Wrong password.'); setPassword(''); } } return (
Restricted

Admin

Unconstrained graph viewer — no entity focus, no hop cap. Password required.

setPassword(e.target.value)} style={{ width:'100%', padding:'10px 12px', borderRadius:8, background:'rgba(255,255,255,0.04)', border:'1px solid var(--border)', color:'var(--fg)', fontSize:14, fontFamily:'inherit', outline:'none', }} /> {error && (
{error}
)} { e.preventDefault(); navigate('/'); }} style={{ display:'block', textAlign:'center', marginTop:18, fontSize:13, color:'var(--fg-mute)', }} >← Back to site
); } function AdminViewer({ navigate, onSignOut }) { // Unconstrained: no focus, no hops, no max_hops → full default behavior. const src = window.api.viewerUrl(null); return (
{ e.preventDefault(); navigate('/'); }} style={{fontSize:13, color:'var(--fg-mute)', flexShrink:0}} >← Site / Admin · Unconstrained Graph FULL ACCESS
{src ? (