`; const blob = new Blob([html],{type:'text/html'}); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'status-page.html'; a.click(); } // ===== UI HELPERS ===== function setView(v) { state.view = v; state.selectedIncident = null; state.search = ''; render(); } function esc(s) { if(!s) return ''; const d=document.createElement('div'); d.textContent=s; return d.innerHTML; } function showTip(e, date, status) { const tip = document.getElementById('tooltip'); tip.innerHTML = `
${date}
${status}
`; tip.style.display = 'block'; tip.style.left = e.clientX + 10 + 'px'; tip.style.top = e.clientY - 40 + 'px'; } function hideTip() { document.getElementById('tooltip').style.display = 'none'; } function toggleKB() { state.showKB = !state.showKB; renderKB(); } function renderKB() { let existing = document.getElementById('kbPanel'); if(existing) existing.remove(); if(!state.showKB) return; const panel = document.createElement('div'); panel.className = 'kb-panel'; panel.id = 'kbPanel'; panel.innerHTML = `

Keyboard Shortcuts

Components1
Incidents2
Maintenance3
Public Page4
Dashboard5
New ComponentC
New IncidentI
Search/
ExportE
CloseEsc
Help?
`; document.body.appendChild(panel); } // Keyboard shortcuts document.addEventListener('keydown', e => { if(state.modal) { if(e.key === 'Escape') { state.modal = null; render(); } if(e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { const saveBtn = document.querySelector('.modal-footer .btn-primary'); if(saveBtn) saveBtn.click(); } return; } if(e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') return; switch(e.key) { case '1': setView('status'); break; case '2': setView('incidents'); break; case '3': setView('maintenance'); break; case '4': setView('public'); break; case '5': setView('dashboard'); break; case 'c': case 'C': openModal('component'); break; case 'i': case 'I': openModal('incident'); break; case '/': e.preventDefault(); state.view='incidents'; render(); setTimeout(()=>{const s=document.querySelector('.search-bar input');if(s)s.focus();},50); break; case 'e': case 'E': exportJSON(); break; case 'Escape': if(state.selectedIncident) { state.selectedIncident=null; render(); } if(state.showKB) { state.showKB=false; renderKB(); } break; case '?': toggleKB(); break; } }); // ===== SEED DATA ===== function seedData() { if(state.components.length > 0) return; // Already has data const now = new Date(); const compIds = { api: id(), web: id(), dash: id(), auth: id(), track: id(), cdn: id(), db: id(), email: id() }; state.settings = { name: 'UTMStamp', description: 'Real-time status of UTMStamp services and infrastructure', url: 'https://status.utmstamp.com', logo: '📊' }; state.components = [ { id: compIds.web, name: 'Website', description: 'utmstamp.com main site', group: 'Core', url: 'https://utmstamp.com', status: 'operational', createdAt: '2026-03-01T00:00:00Z' }, { id: compIds.api, name: 'API', description: 'REST API for signature management', group: 'Core', url: 'https://api.utmstamp.com/health', status: 'operational', createdAt: '2026-03-01T00:00:00Z' }, { id: compIds.dash, name: 'Dashboard', description: 'User dashboard & analytics', group: 'Core', url: 'https://app.utmstamp.com', status: 'operational', createdAt: '2026-03-01T00:00:00Z' }, { id: compIds.auth, name: 'Authentication', description: 'Login, signup, SSO', group: 'Core', url: '', status: 'operational', createdAt: '2026-03-01T00:00:00Z' }, { id: compIds.track, name: 'Click Tracking', description: 'UTM link redirect & analytics pipeline', group: 'Analytics', url: '', status: 'operational', createdAt: '2026-03-01T00:00:00Z' }, { id: compIds.cdn, name: 'CDN / Assets', description: 'Static assets, signature images', group: 'Infrastructure', url: '', status: 'operational', createdAt: '2026-03-01T00:00:00Z' }, { id: compIds.db, name: 'Database', description: 'Primary database cluster', group: 'Infrastructure', url: '', status: 'operational', createdAt: '2026-03-01T00:00:00Z' }, { id: compIds.email, name: 'Email Delivery', description: 'Transactional email (welcome, alerts)', group: 'Infrastructure', url: '', status: 'operational', createdAt: '2026-03-01T00:00:00Z' } ]; // Generate 90 days of uptime history Object.values(compIds).forEach(cid => { state.uptimeHistory[cid] = []; state.responseTime[cid] = []; for(let i = 89; i >= 0; i--) { const d = new Date(now); d.setDate(d.getDate()-i); const key = d.toISOString().split('T')[0]; // Mostly operational with occasional issues let status = 'operational'; const rand = Math.random(); if(cid === compIds.api && i === 12) status = 'partial'; // API had a partial outage 12 days ago else if(cid === compIds.db && i === 45) status = 'degraded'; // DB degraded 45 days ago else if(cid === compIds.cdn && i === 30) status = 'maintenance'; // CDN maintenance 30 days ago else if(rand > 0.98) status = 'degraded'; state.uptimeHistory[cid].push({ date: key, status }); // Response times let baseMs; if(cid === compIds.api) baseMs = 120; else if(cid === compIds.web) baseMs = 85; else if(cid === compIds.dash) baseMs = 150; else if(cid === compIds.track) baseMs = 45; else if(cid === compIds.cdn) baseMs = 25; else baseMs = 100; const ms = Math.round(baseMs + (Math.random()-0.5)*baseMs*0.4); state.responseTime[cid].push({ date: key, ms: Math.max(10, ms) }); } }); // Seed incidents const inc1 = id(), inc2 = id(), inc3 = id(), inc4 = id(), inc5 = id(); state.incidents = [ { id: inc1, type: 'incident', title: 'API latency spike — signature rendering slow', description: 'Users reporting slow signature preview loads. API p99 latency jumped from 150ms to 2.3s.', status: 'resolved', impact: 'minor', affectedComponents: [compIds.api, compIds.dash], createdAt: '2026-04-17T08:30:00Z', resolvedAt: '2026-04-17T10:45:00Z', updates: [ { id: id(), status: 'investigating', message: 'Received reports of slow signature rendering. Investigating API performance.', timestamp: '2026-04-17T08:35:00Z' }, { id: id(), status: 'identified', message: 'Root cause identified: Supabase connection pool exhausted due to a query missing an index on the signatures table. Deploying fix.', timestamp: '2026-04-17T09:15:00Z' }, { id: id(), status: 'monitoring', message: 'Index deployed. p99 latency dropping — now at 280ms and falling. Monitoring.', timestamp: '2026-04-17T09:50:00Z' }, { id: id(), status: 'resolved', message: 'Latency back to normal levels (~140ms p99). Root cause was a missing composite index. Added monitoring alert for connection pool usage.', timestamp: '2026-04-17T10:45:00Z' } ] }, { id: inc2, type: 'incident', title: 'Click tracking pipeline delayed', description: 'UTM click events queued but not processing. Analytics dashboard showing stale data.', status: 'resolved', impact: 'major', affectedComponents: [compIds.track], createdAt: '2026-04-10T14:00:00Z', resolvedAt: '2026-04-10T16:30:00Z', updates: [ { id: id(), status: 'investigating', message: 'Analytics dashboard showing clicks from 2+ hours ago as latest. Pipeline appears stalled.', timestamp: '2026-04-10T14:05:00Z' }, { id: id(), status: 'identified', message: 'Edge function processing click events hit memory limit. Vercel Edge runtime OOM on a batch of 50K clicks from a large team deployment. Implementing batch chunking.', timestamp: '2026-04-10T15:00:00Z' }, { id: id(), status: 'monitoring', message: 'Fix deployed. Backlog of 127K events draining. Currently processing ~2K events/min.', timestamp: '2026-04-10T15:45:00Z' }, { id: id(), status: 'resolved', message: 'All queued events processed. Pipeline running normally with new 10K batch limit. No data was lost.', timestamp: '2026-04-10T16:30:00Z' } ] }, { id: inc3, type: 'incident', title: 'Authentication service 502 errors', description: 'Intermittent 502 errors on login and signup endpoints.', status: 'resolved', impact: 'critical', affectedComponents: [compIds.auth, compIds.api, compIds.dash], createdAt: '2026-03-28T06:15:00Z', resolvedAt: '2026-03-28T07:40:00Z', updates: [ { id: id(), status: 'investigating', message: 'Multiple users unable to log in. Auth endpoints returning 502. All other services operational.', timestamp: '2026-03-28T06:20:00Z' }, { id: id(), status: 'identified', message: 'Supabase Auth service experiencing upstream issues. Confirmed via Supabase status page. We have no action except to wait and retry.', timestamp: '2026-03-28T06:45:00Z' }, { id: id(), status: 'monitoring', message: 'Supabase Auth recovering. Login success rate climbing — now at 94%. Some users may need to retry.', timestamp: '2026-03-28T07:15:00Z' }, { id: id(), status: 'resolved', message: 'All auth services restored. 100% login success rate. Supabase confirmed the issue was a regional node failure in ap-south-1. Adding auth health monitoring endpoint.', timestamp: '2026-03-28T07:40:00Z' } ] }, { id: inc4, type: 'maintenance', title: 'Database migration — new team features schema', description: 'Adding tables and indexes for upcoming team management features. Brief read-only period expected.', status: 'completed', impact: 'minor', affectedComponents: [compIds.db, compIds.api], createdAt: '2026-03-25T00:00:00Z', resolvedAt: '2026-03-27T04:30:00Z', scheduledStart: '2026-03-27T03:00:00Z', scheduledEnd: '2026-03-27T04:00:00Z', updates: [ { id: id(), status: 'scheduled', message: 'Maintenance window scheduled for March 27, 3:00-4:00 AM UTC. API will be in read-only mode during migration.', timestamp: '2026-03-25T10:00:00Z' }, { id: id(), status: 'in_progress', message: 'Migration started. API in read-only mode. Signature viewing works, editing temporarily disabled.', timestamp: '2026-03-27T03:05:00Z' }, { id: id(), status: 'completed', message: 'Migration completed successfully. All services fully operational. New team schema ready.', timestamp: '2026-03-27T04:30:00Z' } ] }, { id: inc5, type: 'maintenance', title: 'CDN cache purge & edge redeployment', description: 'Deploying new edge configuration for faster signature image delivery. Expect brief cache misses.', status: 'scheduled', impact: 'none', affectedComponents: [compIds.cdn], createdAt: '2026-04-28T00:00:00Z', resolvedAt: null, scheduledStart: '2026-05-01T02:00:00Z', scheduledEnd: '2026-05-01T02:30:00Z', updates: [ { id: id(), status: 'scheduled', message: 'Scheduled for May 1, 2:00-2:30 AM UTC. Signature images may load slightly slower for ~5 minutes during cache rebuild.', timestamp: '2026-04-28T10:00:00Z' } ] } ]; // Subscribers state.subscribers = [ { email: 'aj@utmstamp.com', addedAt: '2026-03-01T00:00:00Z' }, { email: 'team@utmstamp.com', addedAt: '2026-03-15T00:00:00Z' }, { email: 'ops-alerts@utmstamp.com', addedAt: '2026-04-01T00:00:00Z' } ]; save(); } // ===== INIT ===== load(); seedData(); render();