// Admin views: Dashboard, Domains, Keys, Firehose, Abuse, Health, Audit, Settings // Wired to backend via window.tmApi (lib/tm-browser.js) // ================= DASHBOARD ================= const AdminDashboard = ({ toast }) => { const [data, setData] = React.useState(null); const [err, setErr] = React.useState(null); const [range, setRange] = React.useState('24h'); // 1h | 24h | 7d | 30d React.useEffect(() => { let cancel = false; setData(null); tmApi.admin.overview({ range }).then((d) => { if (!cancel) setData(d); }).catch((e) => !cancel && setErr(e)); return () => { cancel = true; }; }, [range]); if (err) return ; if (!data) return ; const { stats, volumeHourly, topDomains } = data; return ( <>
{/* Stats grid */}
{stats.map((s) => (
{s.label}
{s.value}
{s.trend === 'up' ? '↗' : '↘'} {s.delta} 24h
))}
{/* Volume chart + Top domains */}
EMAIL VOLUME · {range.toUpperCase()}
{volumeHourly.reduce((a, b) => a + b, 0).toLocaleString()}
{[['1h', '1H'], ['24h', '24H'], ['7d', '7D'], ['30d', '30D']].map(([key, label]) => ( ))}
{axisLabelsForRange(range).map((l, i) => {l})}
TOP DOMAINS · 24H
{topDomains.map((d) => (
@{d.domain} {d.count.toLocaleString()}
))}
{/* Recent activity preview */}
RECENT FIREHOSE
LIVE
); }; const DashboardRecentFirehose = () => { const [items, setItems] = React.useState(null); React.useEffect(() => { let cancel = false; tmApi.admin.firehose.list({ limit: 5 }).then((r) => !cancel && setItems(r)).catch(() => !cancel && setItems([])); return () => { cancel = true; }; }, []); if (!items) return
Loading…
; if (items.length === 0) return
No mail yet
; return (
{items.map((f) => (
{f.ts} {f.from} {f.subject} {f.hasCode && ⚡ {f.code}} {!f.hasCode && }
))}
); }; // Axis labels for the email volume chart at each time range. The chart // width is fixed at 560px; we want ~5 evenly-spaced labels for each range. const axisLabelsForRange = (range) => { if (range === '1h') return ['-60m', '-45m', '-30m', '-15m', 'NOW']; if (range === '7d') return ['-7d', '-5d', '-3d', '-1d', 'NOW']; if (range === '30d') return ['-30d', '-22d', '-15d', '-7d', 'NOW']; return ['00:00', '06:00', '12:00', '18:00', 'NOW']; }; // Shared loading + empty placeholders const AdminLoading = () => (
LOADING…
); const AdminEmpty = ({ title, detail }) => (
{title}
{detail &&
{detail}
}
); // ================= DOMAINS ================= const AdminDomains = ({ toast }) => { const [domains, setDomains] = React.useState(null); const [adding, setAdding] = React.useState(false); const [newDomain, setNewDomain] = React.useState(''); const [dnsModalDomain, setDnsModalDomain] = React.useState(null); const reload = () => tmApi.admin.domains.list().then(setDomains).catch((e) => toast('Load failed: ' + e.message)); React.useEffect(() => { reload(); }, []); if (!domains) return ; const toggle = async (id, enabled) => { try { await tmApi.admin.domains.patch(id, { enabled: !enabled }); reload(); toast('Domain toggled'); } catch (e) { toast('Toggle failed: ' + e.message); } }; const remove = async (id) => { try { await tmApi.admin.domains.remove(id); reload(); toast('Domain removed'); } catch (e) { toast('Remove failed: ' + e.message); } }; const add = async () => { if (!/^[a-z0-9][a-z0-9-]*(\.[a-z0-9][a-z0-9-]*)+$/i.test(newDomain)) return; const target = newDomain; try { await tmApi.admin.domains.create({ domain: target }); toast(`@${target} added`); setNewDomain(''); setAdding(false); reload(); setDnsModalDomain(target); // show DNS instructions } catch (e) { toast('Add failed: ' + e.message); } }; return ( <> d.enabled).length} enabled`}> setAdding(true)}> Add domain
{adding && (
setNewDomain(e.target.value.toLowerCase().trim())} onKeyDown={(e) => e.key === 'Enter' && add()} placeholder="example.com" style={{ flex: 1, background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 13, padding: '8px 12px', borderRadius: 5, outline: 'none' }} /> Add { setAdding(false); setNewDomain(''); }}>Cancel
)} {domains.map((d) => ( ))}
DOMAINSTATUSINBOXESEMAILS 24HSPAM SCORESTORAGEBADGESACTIONS
{d.premium && } @{d.domain}
{d.enabled ? 'ENABLED' : 'DISABLED'} {d.inboxes.toLocaleString()} {d.emails24h.toLocaleString()} 0.1 ? '#DC2626' : d.spamScore > 0.05 ? '#F59E0B' : '#10B981' }}>{d.spamScore.toFixed(2)} {d.storage}
{d.badges.map((b) => )}
setDnsModalDomain(d.domain)}>DNS toggle(d.id, d.enabled)}>{d.enabled ? 'Disable' : 'Enable'} remove(d.id)}>Remove
setDnsModalDomain(null)} toast={toast} /> ); }; // ================= CUSTOMER CUSTOM DOMAINS ================= // Listed below the shared domains table on the same page so admins can see // what every customer key has registered. Read-mostly: admins can remove // for abuse but can't toggle/edit since the customer owns these. const CustomDomainsSection = ({ toast }) => { const [customs, setCustoms] = React.useState(null); const reload = () => tmApi.admin.domains.customs().then(setCustoms).catch((e) => toast?.('Custom domains load failed: ' + e.message)); React.useEffect(() => { reload(); }, []); const remove = async (d) => { if (!confirm(`Remove @${d.domain}? The customer (${d.owner.codePreview}) will lose this domain.`)) return; try { await tmApi.admin.domains.removeCustom(d.id); toast?.(`Removed @${d.domain}`); reload(); } catch (e) { toast?.('Remove failed: ' + e.message); } }; if (!customs) return null; return (

Customer custom domains

{customs.length} · {customs.filter((c) => c.status === 'verified').length} verified
{customs.length === 0 ? (
▒ NO CUSTOM DOMAINS YET ▒
) : ( {customs.map((d) => ( ))}
DOMAINSTATUSOWNER KEYEMAILSRETENTIONADDEDACTIONS
@{d.domain} {d.owner.codePreview} {d.owner.label ? · {d.owner.label} : null} {d.emails.toLocaleString()} {d.retention}h {d.added} remove(d)}>Remove
)}
); }; const CustomStatusPill = ({ status }) => { const map = { verified: { bg: '#0a1f1a', border: '#1a3f33', color: '#10B981' }, pending: { bg: '#3a2a08', border: '#5c3e08', color: '#F59E0B' }, failed: { bg: '#2a0e0e', border: '#5a1a1a', color: '#DC2626' }, }; const s = map[status] || map.failed; return ( {status.toUpperCase()} ); }; // Shows the DNS records the operator must add at the domain's registrar so // inbound mail reaches the relay. Each field rendered separately because most // registrar UIs (Namecheap, Cloudflare, Route 53) have distinct inputs for // Type / Host / Mail Server / Priority — pasting `10 mx.example.com.` into // a single "Mail Server" field doesn't work. const SharedDomainDnsModal = ({ domain, onClose, toast }) => { if (!domain) return null; const relayHost = (typeof window !== 'undefined' && window.location.hostname) || 'zeromailer.cloud'; const mxTarget = 'mx.' + relayHost; const copy = (txt) => { navigator.clipboard?.writeText(txt); toast && toast('Copied'); }; // Color-coded label chips so each DNS field maps unambiguously to the // matching column in registrar UIs. const LABEL_COLORS = { TYPE: { bg: '#3a0e0e', border: '#5a1a1a', color: '#F87171' }, // red HOST: { bg: '#3a2a08', border: '#5c3e08', color: '#F59E0B' }, // orange VALUE: { bg: '#2a3a08', border: '#3e5c08', color: '#FACC15' }, // yellow 'MAIL SERVER': { bg: '#2a3a08', border: '#3e5c08', color: '#FACC15' }, // yellow (same family as value) PRIORITY: { bg: '#0c2a4a', border: '#1e3f6b', color: '#60A5FA' }, // blue }; const Chip = ({ label }) => { const c = LABEL_COLORS[label] || { bg: '#1a1a1a', border: '#262626', color: '#8A8A8A' }; return ( {label} ); }; const Field = ({ label, value }) => { const [copied, setCopied] = React.useState(false); const doCopy = () => { copy(value); setCopied(true); setTimeout(() => setCopied(false), 1200); }; return (
{value}
); }; const Card = ({ type, children, note }) => (
{children} {note &&
{note}
}
); return ( <>

DNS records for @{domain}

SET THESE AT THE REGISTRAR — MAIL WON'T FLOW UNTIL THEN

Open the DNS panel for {domain} at whichever registrar holds it (Namecheap, Cloudflare, Route 53, etc.) and add the records below. The relay will accept mail to anything@{domain} as soon as MX propagates (~5-30 min).

VERIFY WITH
dig {domain} MX +short dig {domain} TXT +short
); }; const Th = ({ children, style }) => {children}; const Label = ({ children }) => {children}; const td = { padding: '11px 16px', fontSize: 12, color: '#EDEDED' }; const tdMono = { ...td, fontFamily: "'JetBrains Mono', monospace", color: '#8A8A8A' }; // ================= KEYS ================= const AdminKeys = ({ toast, onInspect }) => { const [keys, setKeys] = React.useState(null); const [showGen, setShowGen] = React.useState(false); const [newLabel, setNewLabel] = React.useState(''); const [newExp, setNewExp] = React.useState('30d'); const [justCreatedCode, setJustCreatedCode] = React.useState(null); const [hoveredId, setHoveredId] = React.useState(null); const [menuOpenId, setMenuOpenId] = React.useState(null); const reload = () => tmApi.admin.keys.list().then(setKeys).catch((e) => toast('Load failed: ' + e.message)); React.useEffect(() => { reload(); }, []); React.useEffect(() => { if (!menuOpenId) return; const onDoc = (e) => { if (!e.target.closest?.('[data-key-kebab]')) setMenuOpenId(null); }; const onEsc = (e) => { if (e.key === 'Escape') setMenuOpenId(null); }; document.addEventListener('mousedown', onDoc); document.addEventListener('keydown', onEsc); return () => { document.removeEventListener('mousedown', onDoc); document.removeEventListener('keydown', onEsc); }; }, [menuOpenId]); if (!keys) return ; const reactivate = async (k) => { try { await tmApi.admin.keys.reactivate(k.id); toast(`Re-enabled ${k.code}`); reload(); } catch (e) { toast('Re-enable failed: ' + e.message); } }; const extend = async (k, by) => { try { const r = await tmApi.admin.keys.extend(k.id, by); toast(`Extended ${k.code} (now expires ${r.expiresAt ? new Date(r.expiresAt).toLocaleDateString() : 'never'})`); reload(); } catch (e) { toast('Extend failed: ' + e.message); } }; const addKey = async () => { try { const result = await tmApi.admin.keys.create(newLabel, newExp); setJustCreatedCode(result.codeFull); // show full code ONCE reload(); setShowGen(false); setNewLabel(''); setNewExp('30d'); } catch (e) { toast('Generate failed: ' + e.message); } }; const revoke = async (id) => { try { await tmApi.admin.keys.revoke(id); reload(); toast('Key revoked'); } catch (e) { toast('Revoke failed: ' + e.message); } }; const copy = (code) => { navigator.clipboard?.writeText(code); toast('Code copied'); }; return ( <> k.status==='active').length} active`}> Export CSV setShowGen(true)}> Generate key {showGen && (
setNewLabel(e.target.value)} placeholder="Label (optional) — e.g. Alex beta" style={{ background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontSize: 13, padding: '8px 12px', borderRadius: 5, outline: 'none' }} /> Generate setShowGen(false)}>Cancel
)} setJustCreatedCode(null)} toast={toast} />
{keys.map((k) => ( { setHoveredId(k.id); e.currentTarget.style.background = '#101010'; }} onMouseLeave={(e) => { setHoveredId(null); e.currentTarget.style.background = 'transparent'; }} style={{ borderBottom: '1px solid #141414' }} > ))}
CODELABELSTATUSCREATEDEXPIRESINBOXESEMAILSLAST SEENACTIONS
{k.code} {k.hasFullCode && ( )}
{k.label || } {k.created} {k.expires} {k.inboxes} {k.emails} {k.lastSeen} {menuOpenId === k.id && (
e.stopPropagation()} style={{ position: 'absolute', top: '100%', right: 16, marginTop: 4, zIndex: 60, background: '#0f0f0f', border: '1px solid #262626', borderRadius: 6, boxShadow: '0 8px 24px rgba(0,0,0,0.6)', minWidth: 220, overflow: 'hidden', animation: 'slideDown 120ms ease', textAlign: 'left', }} > { setMenuOpenId(null); onInspect(k); }}> Activity {k.hasFullCode && ( { setMenuOpenId(null); copy(k.code); }}> Copy full code )}
Extend expiry {[['24h', '+24 hours'], ['7d', '+7 days'], ['30d', '+30 days'], ['90d', '+90 days'], ['never', 'No expiry']].map(([by, label]) => ( { setMenuOpenId(null); extend(k, by); }}> {label} ))} {(k.status === 'revoked' || k.status === 'expired') && ( <>
{ setMenuOpenId(null); reactivate(k); }}> ↻ Re-enable key )} {k.status === 'active' && ( <>
{ if (!confirm(`Revoke ${k.code}? Sessions will be invalidated immediately.`)) return; setMenuOpenId(null); revoke(k.id); }}> Revoke key )}
)}
); }; // Modal shown ONCE when a fresh access key is generated. The full code is // argon2-hashed in the DB so this is the only chance to copy it. const NewKeyModal = ({ code, onClose, toast }) => { const [acknowledged, setAcknowledged] = React.useState(false); const [copied, setCopied] = React.useState(false); React.useEffect(() => { if (code) { setAcknowledged(false); setCopied(false); } }, [code]); if (!code) return null; const doCopy = () => { navigator.clipboard?.writeText(code); setCopied(true); toast && toast('Code copied to clipboard'); }; return ( <>
FULL CODE — SHOWN ONCE

Copy this access code now. It's argon2-hashed in the database — once you close this dialog there is no way to retrieve it. If you lose it, you'll need to revoke this key and generate a new one.

{code}

The keys list will only show the redacted preview {code.slice(0,4)}-XXXX-XXXX-{code.slice(-4)} from now on.

); }; const KeyMenuItem = ({ children, onClick, danger, accent }) => ( ); const KeyMenuLabel = ({ children }) => (
{children}
); const StatusPill = ({ status }) => { const map = { active: { bg: '#0a1f1a', border: '#1a3f33', color: '#10B981' }, revoked: { bg: '#2a0e0e', border: '#5a1a1a', color: '#DC2626' }, expired: { bg: '#1a1a1a', border: '#262626', color: '#8A8A8A' }, unused: { bg: '#0c2a4a', border: '#1e3f6b', color: '#60A5FA' }, }; const s = map[status] || map.expired; return ( {status.toUpperCase()} ); }; // ================= FIREHOSE ================= const AdminFirehose = ({ toast }) => { const [stream, setStream] = React.useState([]); const [paused, setPaused] = React.useState(false); const [filter, setFilter] = React.useState(''); const [selected, setSelected] = React.useState(null); const [loaded, setLoaded] = React.useState(false); const [detail, setDetail] = React.useState(null); const [detailLoading, setDetailLoading] = React.useState(false); const [detailErr, setDetailErr] = React.useState(null); // Inspector pane is resizable via the vertical splitter between Stream and Inspector. // Width persists per-browser in localStorage. const [inspectorWidth, setInspectorWidth] = React.useState(() => { if (typeof window === 'undefined') return 480; const saved = parseInt(window.localStorage.getItem('admin.firehose.inspectorWidth') || '', 10); return Number.isFinite(saved) && saved >= 320 ? saved : 480; }); const splitContainerRef = React.useRef(null); const onSplitMouseDown = React.useCallback((e) => { e.preventDefault(); let lastWidth = null; const onMove = (ev) => { const node = splitContainerRef.current; if (!node) return; const rect = node.getBoundingClientRect(); const desired = rect.right - ev.clientX; const max = Math.max(360, rect.width - 280); const next = Math.min(max, Math.max(320, desired)); lastWidth = next; setInspectorWidth(next); }; const onUp = () => { document.body.style.cursor = ''; document.body.style.userSelect = ''; window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); if (lastWidth != null) { try { window.localStorage.setItem('admin.firehose.inspectorWidth', String(Math.round(lastWidth))); } catch (_) { /* ignore */ } } }; document.body.style.cursor = 'col-resize'; document.body.style.userSelect = 'none'; window.addEventListener('mousemove', onMove); window.addEventListener('mouseup', onUp); }, []); // Fetch full email detail on selection (sanitized HTML body, headers, attachments, raw MIME url). // Each call writes an admin_audit row (action: "message.view") server-side. React.useEffect(() => { if (!selected?.id) { setDetail(null); setDetailErr(null); return; } let cancel = false; setDetailLoading(true); setDetailErr(null); setDetail(null); tmApi.admin.messages.get(selected.id).then((d) => { if (cancel) return; setDetail(d); setDetailLoading(false); }).catch((e) => { if (cancel) return; setDetailErr(e?.message || 'Failed to load body'); setDetailLoading(false); }); return () => { cancel = true; }; }, [selected?.id]); // Initial load React.useEffect(() => { let cancel = false; tmApi.admin.firehose.list({ limit: 50 }).then((r) => { if (cancel) return; setStream(r); setSelected(r[0] || null); setLoaded(true); }).catch((e) => { setLoaded(true); toast('Firehose load failed: ' + e.message); }); return () => { cancel = true; }; }, []); // Live WS stream React.useEffect(() => { if (paused) return; const conn = tmApi.openFirehose({ onEntry: (entry) => setStream((p) => [{ ...entry, isNew: true }, ...p].slice(0, 200)), onError: () => { /* will be retried on next mount */ }, }); return () => conn.close(); }, [paused]); const filtered = filter ? stream.filter(f => (f.from + f.subject + f.to + f.domain).toLowerCase().includes(filter.toLowerCase())) : stream; const refresh = async () => { try { const r = await tmApi.admin.firehose.list({ limit: 50 }); setStream(r); toast('Firehose refreshed'); } catch (e) { toast('Refresh failed: ' + e.message); } }; if (!loaded) return ; return ( <> {filtered.length} {paused ? 'PAUSED' : 'LIVE'} } >
setFilter(e.target.value)} placeholder="Filter sender / subject / domain" style={{ background: '#141414', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 11, padding: '7px 10px 7px 26px', borderRadius: 5, outline: 'none', width: 260 }} />
Refresh setPaused(!paused)}> {paused ? <> Resume : <> Pause}
{/* Stream */}
{filtered.map((f) => (
setSelected(f)} style={{ display: 'grid', gridTemplateColumns: '70px 1fr auto 70px', gap: 10, padding: '9px 16px', borderBottom: '1px solid #141414', cursor: 'pointer', alignItems: 'center', background: selected?.id === f.id ? '#141414' : 'transparent', borderLeft: `2px solid ${selected?.id === f.id ? '#F59E0B' : f.flagged ? '#DC2626' : 'transparent'}`, animation: f.isNew ? 'newMail 1.8s ease' : 'none', }} onMouseEnter={(e) => selected?.id !== f.id && (e.currentTarget.style.background = '#101010')} onMouseLeave={(e) => selected?.id !== f.id && (e.currentTarget.style.background = 'transparent')} > {f.ts}
{f.flagged && } {f.from} {f.to}
{f.subject}
{f.hasCode ? ( ⚡ {f.code} ) : } {f.size}
))}
{/* Splitter — drag to resize the inspector pane */}
{ setInspectorWidth(480); try { window.localStorage.removeItem('admin.firehose.inspectorWidth'); } catch (_) {} }} title="Drag to resize · double-click to reset" style={{ cursor: 'col-resize', background: '#1f1f1f', position: 'relative', userSelect: 'none' }} onMouseEnter={(e) => (e.currentTarget.style.background = '#F59E0B')} onMouseLeave={(e) => (e.currentTarget.style.background = '#1f1f1f')} >
{/* Inspector */}
{selected ? ( <>
INSPECTION · {selected.id}
{selected.ts} {selected.from} {selected.to} {selected.domain} {selected.keyId} {selected.size} {selected.flagged ? 'YES' : 'NO'} {selected.hasCode && (<>{selected.code})}
SUBJECT
{selected.subject}
BODY{detail?.attachments?.length ? ` · ${detail.attachments.length} ATTACH` : ''}
{detailLoading ? (
Loading body…
) : detailErr ? (
Failed to load: {detailErr}
) : detail?.body ? (