Skip to content

Repository files, collaboration, releases and project activity.

ARCHFORGE HISTORY

Blame · src/views.js

Branch main · the Commit author is not necessarily a verified ArchForge account.

e59b7f7cc6archadmin2026-10-111 'use strict';
e59b7f7cc6archadmin2026-10-112 const {esc}=require('./security');
e59b7f7cc6archadmin2026-10-113 const {now}=require('./database');
2109dd33b8archadmin2026-10-124 const {serviceLabel}=require('./branding');
e59b7f7cc6archadmin2026-10-115 const fmt=t=>t?new Date(Number(t)*1000).toLocaleString('en-GB',{dateStyle:'medium',timeStyle:'short',timeZone:'UTC'})+' UTC':'Not measured';
e59b7f7cc6archadmin2026-10-116 function layout(title,body,{admin=false,notice='',meta='Independent uptime monitoring for ArchForge',refresh=false}={}){
e59b7f7cc6archadmin2026-10-117 return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="dark"><meta name="description" content="${esc(meta)}"><title>${esc(title)} — ArchForge Status</title><link href="/assets/style.css" rel="stylesheet">${refresh?'<meta http-equiv="refresh" content="65">':''}</head><body>
e59b7f7cc6archadmin2026-10-118 <header class="topbar"><div class="wrap top-inner"><a href="/" class="brand"><span class="brand-icon">◈</span><span><b>ArchForge <em>Status</em></b><small>Independent monitoring</small></span></a><nav aria-label="Main navigation"><a href="/">Overview</a><a href="/#incidents">Incidents</a><a href="/#maintenance">Maintenance</a><a href="/subscribe">Alerts</a>${admin?'<a href="/admin">Admin</a>':'<a href="/admin/login">Admin login</a>'}</nav></div></header>
e59b7f7cc6archadmin2026-10-119 <main class="wrap">${notice?`<div class="notice">${esc(notice)}</div>`:''}${body}</main><footer class="wrap footer"><span>ArchForge External Status · Independent from the main platform</span><span>Times shown in UTC · <a href="https://archforge.nl" rel="noopener noreferrer">Main website ↗</a></span></footer></body></html>`;
e59b7f7cc6archadmin2026-10-1110 }
e59b7f7cc6archadmin2026-10-1111 function badge(state){const cls=state==='operational'?'good':state==='offline'?'bad':['maintenance','degraded'].includes(state)?'warn':'muted';const label={operational:'Operational',offline:'Outage',unknown:'No data',maintenance:'Maintenance',degraded:'Degraded'}[state]||state;return `<span class="badge ${cls}"><i class="dot"></i>${esc(label)}</span>`;}
e59b7f7cc6archadmin2026-10-1112 function icon(id){return ({website:'◉',api:'⌘',git_http:'⌁',git_ssh:'⤳',dns:'⊕',tls:'⬡'})[id]||'◈';}
e59b7f7cc6archadmin2026-10-1113 function timeline(service){const dates=service.stats.buckets;let month='',chunks=[];for(const b of dates){const m=b.day.slice(0,7);if(m!==month){month=m;chunks.push({label:new Date(b.day+'T12:00:00Z').toLocaleDateString('en-GB',{month:'short',year:'numeric',timeZone:'UTC'}),days:[]});}chunks[chunks.length-1].days.push(b);}
e59b7f7cc6archadmin2026-10-1114 return `<div class="history" aria-label="Last ${service.stats.days} days of monitoring">${chunks.map(c=>`<div class="history-month"><div class="month-label">${esc(c.label)}</div><div class="history-bars cols-${c.days.length}">${c.days.map(d=>`<span class="day ${d.state==='operational'?'green':d.state==='outage'?'red':d.state==='degraded'?'amber':'grey'}" title="${esc(d.day)}: ${d.count===0?'No measurements':`${d.successful}/${d.count} successful checks`}" aria-label="${esc(d.day)}: ${d.state==='unknown'?'no data':d.state}"></span>`).join('')}</div></div>`).join('')}</div>`;}
e59b7f7cc6archadmin2026-10-1115 function percent(stats){return stats.uptime===null?'<span class="muted">Collecting measurements</span>':`<strong>${stats.uptime.toFixed(2)}%</strong> <span class="muted">observed availability</span>`;}
2109dd33b8archadmin2026-10-1216 function card(service){return `<article class="service-card"><div class="service-header"><div class="service-heading"><span class="service-icon">${icon(service.id)}</span><div><h3><a href="/services/${encodeURIComponent(service.id)}">${esc(serviceLabel(service))}</a></h3><p>${esc(service.description)}</p></div></div>${badge(service.current_state)}</div>${timeline(service)}<div class="service-footer"><span>${percent(service.stats)}</span><span class="muted">${service.stats.coverage}/${service.stats.days} days measured</span></div></article>`;}
e59b7f7cc6archadmin2026-10-1117 function formCsrf(token){return `<input type="hidden" name="csrf" value="${esc(token)}">`;}
e59b7f7cc6archadmin2026-10-1118 function homepage({services,days,incidents,maintenance,config,admin=false}){
e59b7f7cc6archadmin2026-10-1119 const outages=services.filter(s=>s.current_state==='offline').length;const degraded=services.filter(s=>s.current_state==='degraded').length;const unknown=services.filter(s=>s.current_state==='unknown').length;
e59b7f7cc6archadmin2026-10-1120 const majorIncident=incidents.some(i=>!i.resolved_at&&i.severity==='outage');const minorIncident=incidents.some(i=>!i.resolved_at&&i.severity==='degraded');
e59b7f7cc6archadmin2026-10-1121 const active=maintenance.some(m=>m.starts_at<=Math.floor(Date.now()/1000)&&m.ends_at>Math.floor(Date.now()/1000));const title=outages||majorIncident?'Active outage or major incident':degraded||minorIncident?'Some services are degraded':active?'Scheduled maintenance in progress':unknown?'Monitoring in progress':'All monitored services operational';
e59b7f7cc6archadmin2026-10-1122 const state=outages||majorIncident?'bad':degraded||minorIncident||active?'warn':unknown?'muted':'good';
e59b7f7cc6archadmin2026-10-1123 const body=`<section class="hero"><div class="eyebrow">LIVE EXTERNAL STATUS <span class="pulse"></span></div><h1>ArchForge infrastructure,<br><span>without the guesswork.</span></h1><p>Independently verified on a separate Debian server. The monitor continues collecting evidence even if the main website goes down.</p><div class="hero-state ${state}"><span class="hero-state-icon">${outages||majorIncident?'!':degraded||minorIncident||active?'⌛':unknown?'…':'✓'}</span><div><strong>${title}</strong><small>${outages||majorIncident?'An outage or incident is being tracked independently. Check incident history below.':degraded||minorIncident?'Some checks or published incidents require attention.':unknown?'Some services have not yet met the confirmation threshold.':active?'See maintenance windows below.':'External checks report no confirmed service failures.'}</small></div></div></section>
e59b7f7cc6archadmin2026-10-1124 <section class="stat-grid" aria-label="Status summary"><div class="stat-card"><span>Tracked services</span><strong>${services.length}</strong></div><div class="stat-card"><span>Confirmed outages</span><strong class="${outages?'danger':''}">${outages}</strong></div><div class="stat-card"><span>Current maintenance</span><strong>${maintenance.length}</strong></div><div class="stat-card"><span>Monitoring source</span><strong class="source">VPS 2</strong></div></section>
e59b7f7cc6archadmin2026-10-1125 <section class="section-head"><div><span class="eyebrow">SERVICE HEALTH</span><h2>Monitored services</h2></div><div class="period" role="group" aria-label="History period">${[7,30,90].map(d=>`<a class="${d===days?'selected':''}" href="/?days=${d}">${d} days</a>`).join('')}</div></section><p class="caption">Unknown days are not counted as healthy. Some checks verify reachability only and cannot prove full feature availability.</p>
e59b7f7cc6archadmin2026-10-1126 <div class="services">${services.map(card).join('')||'<p class="empty">No configured monitoring services yet.</p>'}</div>
e59b7f7cc6archadmin2026-10-1127 <section class="lower-grid"><div id="incidents" class="panel"><div class="panel-heading"><div><span class="eyebrow">TRANSPARENCY</span><h2>Incident history</h2></div></div>${incidents.length?incidents.map(i=>`<div class="event"><span class="event-marker ${i.resolved_at?'green':'red'}"></span><div><strong><a href="/incidents/${i.id}">${esc(i.title)}</a></strong><p>${esc(i.description)}</p><small>${fmt(i.started_at)} · ${i.resolved_at?'Resolved':'Ongoing'}</small></div></div>`).join(''):'<p class="empty">No incidents recorded yet.</p>'}</div>
e59b7f7cc6archadmin2026-10-1128 <div id="maintenance" class="panel"><div class="panel-heading"><div><span class="eyebrow">PLANNED WORK</span><h2>Maintenance</h2></div></div>${maintenance.length?maintenance.map(m=>`<div class="event"><span class="event-marker amber"></span><div><strong>${esc(m.title)}</strong><p>${esc(m.description)}</p><small>${fmt(m.starts_at)} – ${fmt(m.ends_at)}</small></div></div>`).join(''):'<p class="empty">No active or upcoming maintenance windows.</p>'}<a href="/subscribe" class="secondary-link">Get independent outage notifications →</a></div></section>`;
e59b7f7cc6archadmin2026-10-1129 return layout('Overview',body,{admin,refresh:true});
e59b7f7cc6archadmin2026-10-1130 }
2109dd33b8archadmin2026-10-1231 function details(service,incidents,days,admin){const body=`<div class="page-head"><a href="/" class="back">← All services</a><div class="service-title"><div><span class="eyebrow">SERVICE DETAILS</span><h1>${esc(serviceLabel(service))}</h1><p>${esc(service.description)}</p></div>${badge(service.current_state)}</div></div><div class="stat-grid"><div class="stat-card"><span>Observed uptime</span><strong>${service.stats.uptime===null?'No data':service.stats.uptime.toFixed(2)+'%'}</strong></div><div class="stat-card"><span>Days covered</span><strong>${service.stats.coverage}/${days}</strong></div><div class="stat-card"><span>Last latency</span><strong>${service.last_latency===null?'Unknown':service.last_latency+'ms'}</strong></div><div class="stat-card"><span>Last checked</span><strong class="source">${fmt(service.last_checked)}</strong></div></div><div class="panel section"><div class="section-head"><h2>Independent monitoring history</h2><div class="period">${[7,30,90].map(d=>`<a href="/services/${esc(service.id)}?days=${d}" class="${d===days?'selected':''}">${d} days</a>`).join('')}</div></div>${timeline(service)}<p class="caption">Checks measure this endpoint only. An unknown interval indicates missing monitoring data.</p></div><div class="panel section"><h2>Related incidents</h2>${incidents.length?incidents.map(i=>`<div class="event"><span class="event-marker ${i.resolved_at?'green':'red'}"></span><div><strong><a href="/incidents/${i.id}">${esc(i.title)}</a></strong><p>${esc(i.description)}</p><small>${fmt(i.started_at)}</small></div></div>`).join(''):'<p class="empty">No incidents found for this service.</p>'}</div>`;return layout(serviceLabel(service),body,{admin});}
e59b7f7cc6archadmin2026-10-1132 function incidentPage(i,updates,admin){return layout('Incident',`<div class="page-head"><a class="back" href="/">← Back to overview</a><span class="eyebrow">INCIDENT DETAILS</span><h1>${esc(i.title)}</h1><p>${esc(i.description)}</p>${badge(i.resolved_at?'operational':i.severity==='degraded'?'degraded':'offline')}<p class="caption">Opened ${fmt(i.started_at)} ${i.resolved_at?' · Resolved '+fmt(i.resolved_at):''}</p></div><section class="panel section"><h2>Timeline</h2>${updates.map(u=>`<div class="event"><span class="event-marker ${u.state==='resolved'?'green':'amber'}"></span><div><strong>${esc(u.state)}</strong><p>${esc(u.body)}</p><small>${fmt(u.created_at)}</small></div></div>`).join('')}</section>`,{admin});}
e59b7f7cc6archadmin2026-10-1133 function subscribe(csrf,{message='',email=''}={}){return layout('Email alerts',`<div class="page-head narrow"><span class="eyebrow">NEVER MISS AN INCIDENT</span><h1>Independent email alerts</h1><p>Opt in for outage and recovery notifications from VPS 2. Confirm your email to activate alerts. Unsubscribe any time.</p></div><div class="panel narrow">${message?`<div class="notice">${esc(message)}</div>`:''}<form method="post" action="/subscribe">${formCsrf(csrf)}<label for="email">Email address</label><input required type="email" maxlength="254" name="email" id="email" value="${esc(email)}" placeholder="you@example.com"><input name="website" class="hidden-trap" tabindex="-1" autocomplete="off" aria-hidden="true"><button class="button">Send confirmation email</button></form><p class="caption">No account needed. Email is stored on the independent status server, never forwarded to ArchForge.</p></div>`);}
e59b7f7cc6archadmin2026-10-1134 function adminLogin(csrf,msg=''){return layout('Admin login',`<div class="page-head narrow"><span class="eyebrow">SECURE ADMIN ACCESS</span><h1>Sign in</h1><p>Independent account with a password and a six-digit authenticator code.</p></div><div class="panel narrow">${msg?`<div class="notice">${esc(msg)}</div>`:''}<form method="post" action="/admin/login">${formCsrf(csrf)}<label>Username<input name="username" autocomplete="username" required maxlength="80"></label><label>Password<input type="password" name="password" autocomplete="current-password" required></label><label>Authenticator code<input name="totp" inputmode="numeric" pattern="[0-9]{6}" maxlength="6" autocomplete="one-time-code" required></label><button class="button">Sign in securely</button></form></div>`);}
e59b7f7cc6archadmin2026-10-1135 function adminDashboard({csrf,services,incidents,maintenance,queue,notice=''}){
e59b7f7cc6archadmin2026-10-1136 return layout('Administration',`<div class="page-head"><span class="eyebrow">ADMINISTRATION · EXTERNAL STATUS</span><h1>Control center</h1><p>Manage announcements independently of the primary ArchForge server.</p><form method="post" action="/admin/logout">${formCsrf(csrf)}<button class="button secondary">Sign out</button></form></div>${notice?`<div class="notice">${esc(notice)}</div>`:''}<div class="stat-grid"><div class="stat-card"><span>Services</span><strong>${services.length}</strong></div><div class="stat-card"><span>Open incidents</span><strong>${incidents.filter(i=>!i.resolved_at).length}</strong></div><div class="stat-card"><span>Maintenance windows</span><strong>${maintenance.length}</strong></div><div class="stat-card"><span>Unsent notifications</span><strong>${queue}</strong></div></div>
2109dd33b8archadmin2026-10-1237 <div class="admin-grid"><div class="panel"><h2>Services</h2>${services.map(s=>`<div class="admin-row"><span>${esc(serviceLabel(s))} <small>${esc(s.id)}</small></span>${badge(s.current_state)}</div>`).join('')}<p class="caption">Monitoring targets are configured locally in status.env to prevent arbitrary network probing.</p></div>
2109dd33b8archadmin2026-10-1238 <div class="panel"><h2>Publish an incident</h2><form method="post" action="/admin/incidents">${formCsrf(csrf)}<label>Title<input name="title" maxlength="140" required></label><label>Affected service<select name="service">${services.map(s=>`<option value="${esc(s.id)}">${esc(serviceLabel(s))}</option>`).join('')}<option value="">Platform-wide / general</option></select></label><label>Severity<select name="severity"><option value="degraded">Degraded performance</option><option value="outage">Major outage</option></select></label><label>Public description<textarea name="description" required maxlength="3000" rows="4"></textarea></label><button class="button">Publish incident</button></form></div>
e59b7f7cc6archadmin2026-10-1139 <div class="panel"><h2>Incident updates</h2>${incidents.slice(0,15).map(i=>`<div class="incident-admin"><strong>${esc(i.title)}</strong><small>${esc(i.state)} · ${fmt(i.started_at)}</small>${!i.resolved_at?`<form method="post" action="/admin/incidents/${i.id}/update">${formCsrf(csrf)}<label>State<select name="state"><option value="identified">Identified</option><option value="monitoring">Monitoring</option><option value="investigating">Investigating</option><option value="resolved">Resolved</option></select></label><label>Public update<textarea name="body" required maxlength="3000" rows="2"></textarea></label><button class="button secondary">Add update</button></form>`:''}</div>`).join('')||'<p class="empty">No incidents.</p>'}</div>
2109dd33b8archadmin2026-10-1240 <div class="panel"><h2>Schedule maintenance</h2><form method="post" action="/admin/maintenance">${formCsrf(csrf)}<label>Title<input name="title" required maxlength="140"></label><label>Service<select name="service"><option value="">All services</option>${services.map(s=>`<option value="${esc(s.id)}">${esc(serviceLabel(s))}</option>`).join('')}</select></label><label>Start time (UTC)<input name="start" type="datetime-local" required></label><label>End time (UTC)<input name="end" type="datetime-local" required></label><label>Public description<textarea name="description" required maxlength="3000" rows="3"></textarea></label><button class="button">Schedule maintenance</button></form>${maintenance.map(m=>`<div class="admin-row"><span>${esc(m.title)}<small>${fmt(m.starts_at)}</small></span><form method="post" action="/admin/maintenance/${m.id}/delete">${formCsrf(csrf)}<button class="button secondary small">Remove</button></form></div>`).join('')}</div></div>` ,{admin:true});
e59b7f7cc6archadmin2026-10-1141 }
e59b7f7cc6archadmin2026-10-1142 module.exports={layout,badge,fmt,homepage,details,incidentPage,subscribe,adminLogin,adminDashboard};