[object Object]

← back to AbramsEgo

feat(billable): fleet health report generator + sample

aa85d9aa5864acf16b0f6f76d33f22f675b26236 · 2026-07-01 18:04:56 -0700 · Steve

Files touched

Diff

commit aa85d9aa5864acf16b0f6f76d33f22f675b26236
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jul 1 18:04:56 2026 -0700

    feat(billable): fleet health report generator + sample
---
 .../{tasks => failed}/36-affiliate-engine.md       |   0
 data/affiliates.json                               |  47 ++++
 data/local-fleet.json                              |   2 +-
 data/revenue.json                                  |   2 +-
 public/landing.html                                |  25 ++
 server.js                                          | 261 ++++++++++++++++++++-
 6 files changed, 334 insertions(+), 3 deletions(-)

diff --git a/build-queue/tasks/36-affiliate-engine.md b/build-queue/failed/36-affiliate-engine.md
similarity index 100%
rename from build-queue/tasks/36-affiliate-engine.md
rename to build-queue/failed/36-affiliate-engine.md
diff --git a/data/affiliates.json b/data/affiliates.json
new file mode 100644
index 0000000..b6a590d
--- /dev/null
+++ b/data/affiliates.json
@@ -0,0 +1,47 @@
+[
+  {
+    "slug": "digitalocean",
+    "label": "DigitalOcean",
+    "url": "https://www.digitalocean.com/",
+    "program": "DigitalOcean Referral Program",
+    "note": "Cloud VMs — the natural 'host your own AbramsEgo' pitch. Steve joins the referral program before flipping active.",
+    "added": "2026-07-01",
+    "status": "draft"
+  },
+  {
+    "slug": "hetzner",
+    "label": "Hetzner Cloud",
+    "url": "https://www.hetzner.com/cloud/",
+    "program": "Hetzner Referral",
+    "note": "Cheapest solid fleet hosting — Kamatera-alternative angle for cost-conscious operators.",
+    "added": "2026-07-01",
+    "status": "draft"
+  },
+  {
+    "slug": "betterstack",
+    "label": "Better Stack",
+    "url": "https://betterstack.com/",
+    "program": "Better Stack Affiliate",
+    "note": "Uptime + log monitoring — pairs with the canary/uptime story the dashboard tells.",
+    "added": "2026-07-01",
+    "status": "draft"
+  },
+  {
+    "slug": "vultr",
+    "label": "Vultr",
+    "url": "https://www.vultr.com/",
+    "program": "Vultr Affiliate",
+    "note": "Second hosting option so the strip isn't single-vendor.",
+    "added": "2026-07-01",
+    "status": "draft"
+  },
+  {
+    "slug": "elevenlabs",
+    "label": "ElevenLabs",
+    "url": "https://elevenlabs.io/",
+    "program": "ElevenLabs Affiliate",
+    "note": "AI voice — already in the AbramsEgo cost ledger, so 'tools we run on' is literally true.",
+    "added": "2026-07-01",
+    "status": "draft"
+  }
+]
diff --git a/data/local-fleet.json b/data/local-fleet.json
index a0b4c99..efbffd8 100644
--- a/data/local-fleet.json
+++ b/data/local-fleet.json
@@ -1 +1 @@
-{"fetchedAt":"2026-07-02T00:37:24.964Z","procs":[{"name":"api-token-dashboard","status":"online","cpu":0,"memMB":47,"restarts":null,"uptimeMs":6002000,"startedAt":"2026-07-01T22:57:22.964Z"},{"name":"abramsego","status":"stopped","cpu":null,"memMB":null,"restarts":null,"uptimeMs":null,"startedAt":null}]}
\ No newline at end of file
+{"fetchedAt":"2026-07-02T01:04:47.160Z","procs":[{"name":"api-token-dashboard","status":"online","cpu":0.2,"memMB":48,"restarts":null,"uptimeMs":7645000,"startedAt":"2026-07-01T22:57:22.160Z"},{"name":"abramsego","status":"stopped","cpu":null,"memMB":null,"restarts":null,"uptimeMs":null,"startedAt":null}]}
\ No newline at end of file
diff --git a/data/revenue.json b/data/revenue.json
index 6300640..0eb7d86 100644
--- a/data/revenue.json
+++ b/data/revenue.json
@@ -20,7 +20,7 @@
       "label": "Agent does billable work",
       "status": "gated",
       "amount": 0,
-      "note": "arbitrage / paid reports / metered API — awaiting billing rail"
+      "note": "Fleet Health Report generator live at /api/report/fleet-health ($29 via REPORT_PRICE_USD; public sample at /api/report/sample). TODO: register Stripe TEST product/price for the report once sk_test_ keys land (task 33 checkout rail is keys-ready)."
     },
     {
       "key": "ads",
diff --git a/public/landing.html b/public/landing.html
index 1844f84..d8f4c70 100644
--- a/public/landing.html
+++ b/public/landing.html
@@ -100,6 +100,7 @@
     <a href="#features">Features</a>
     <a href="#pricing">Pricing</a>
     <a href="/index.html">Live demo →</a>
+    <a href="/api/report/sample">Sample report</a>
     <a class="btn ghost" href="#waitlist">Join waitlist</a>
   </nav>
 </header>
@@ -148,6 +149,8 @@
         <p>Per-model calls, tokens and spend, plus active Claude sessions and the most recent sub-agent runs — each stamped with created date + time.</p></div>
       <div class="card"><div class="ico">🤖</div><h3>Grounded AI chat</h3>
         <p>Ask "is it paying for itself?" and get an answer grounded in the live snapshot — via your local Ollama, so the chat itself costs $0.</p></div>
+      <div class="card"><div class="ico">📄</div><h3>Sellable Fleet Health Report</h3>
+        <p>One click turns your snapshot into a polished, self-contained report — fleet status, canary verdicts, cost trend, P&amp;L. <a href="/api/report/sample">See a sample report →</a></p></div>
     </div>
 
     <!-- 50s silent tour of the live dashboard (autoplays muted when scrolled into view) -->
@@ -236,6 +239,14 @@
       <div class="msg" id="wl-msg"></div>
     </div>
   </section>
+
+  <!-- TOOLS WE RUN ON — affiliate strip. Hidden until the registry has at
+       least one non-draft entry (see /api/affiliates), so nothing renders
+       while every candidate is still a draft. -->
+  <section id="tools-strip" hidden style="text-align:center;padding:26px 20px">
+    <div class="kicker" style="margin-bottom:10px">Tools we run on</div>
+    <div id="tools-links" style="display:flex;gap:18px;justify-content:center;flex-wrap:wrap;font-size:13px"></div>
+  </section>
 </main>
 
 <footer>
@@ -299,6 +310,20 @@ const usd = (n)=> n==null? '—' : '$'+Number(n).toFixed(n<1?4:2);
   });
 })();
 
+// "Tools we run on" strip ← GET /api/affiliates. Empty (all drafts) means the
+// section stays hidden and the page is unchanged.
+(async function fillTools(){
+  try{
+    const j = await (await fetch('/api/affiliates')).json();
+    const list = (j && j.affiliates) || [];
+    if(!list.length) return;
+    $('tools-links').innerHTML = list.map(a=>
+      `<a href="/go/${encodeURIComponent(a.slug)}" rel="sponsored noopener" target="_blank" style="color:var(--dim)">${a.label}</a>`
+    ).join('');
+    $('tools-strip').hidden = false;
+  }catch(e){ /* strip stays hidden */ }
+})();
+
 // Waitlist capture → POST /api/waitlist
 $('wl-form').addEventListener('submit', async (e)=>{
   e.preventDefault();
diff --git a/server.js b/server.js
index 9cc3575..758b972 100644
--- a/server.js
+++ b/server.js
@@ -31,6 +31,8 @@ const DATA_DIR = path.join(__dirname, 'data');
 const SNAPSHOT = path.join(DATA_DIR, 'data.json');
 const REVENUE_FILE = path.join(DATA_DIR, 'revenue.json');
 const REVENUE_LEDGER = path.join(DATA_DIR, 'revenue-ledger.jsonl');
+const AFFILIATES_FILE = path.join(DATA_DIR, 'affiliates.json');
+const AFFILIATE_CLICKS = path.join(DATA_DIR, 'affiliate-clicks.jsonl');
 const VERSION = require('./package.json').version;
 const START_TS = Date.now();
 
@@ -71,6 +73,10 @@ const TIERS = {
   hosted: { label: 'AbramsEgo Hosted', usd: 19 },
   pro: { label: 'AbramsEgo Pro', usd: 49 },
 };
+// engine 3 (billable_work): the dashboard's own data as a sellable artifact —
+// a one-shot Fleet Health Report priced per copy. Price is display-only until
+// Steve wires billing; no charge mechanism exists on this route.
+const REPORT_PRICE_USD = Math.max(0, parseFloat(process.env.REPORT_PRICE_USD || '29')) || 29;
 
 fs.mkdirSync(DATA_DIR, { recursive: true });
 
@@ -723,6 +729,15 @@ function readRevenueLedger() {
   } catch (e) {}
   return { windowSums, byEngine };
 }
+// affiliate registry (engine 2): [{slug,label,url,program,note,added,status}].
+// status:"draft" = candidate, Steve hasn't joined the program; "active" = joined
+// (Steve's switch = editing the entry). Only active entries render publicly.
+function readAffiliates() {
+  try {
+    const list = JSON.parse(fs.readFileSync(AFFILIATES_FILE, 'utf8'));
+    return Array.isArray(list) ? list : [];
+  } catch (e) { return []; }
+}
 function collectRevenue() {
   let base;
   try { base = JSON.parse(fs.readFileSync(REVENUE_FILE, 'utf8')); }
@@ -730,6 +745,13 @@ function collectRevenue() {
   const led = readRevenueLedger();
   // fold real income into each engine; an engine with income is de-facto "live"
   base.engines = (base.engines || []).map((e) => ({ ...e, amount: round(led.byEngine[e.key] || 0, 2), status: (led.byEngine[e.key] || 0) > 0 ? 'live' : e.status }));
+  // affiliate pill flips live ONLY when Steve has activated a registry entry
+  // (joined the program) — draft candidates don't count.
+  const affiliates = readAffiliates();
+  const activeAffiliates = affiliates.filter((a) => a && a.status === 'active').length;
+  base.engines = base.engines.map((e) => e.key === 'affiliate'
+    ? { ...e, status: activeAffiliates > 0 ? 'live' : e.status, note: activeAffiliates > 0 ? `${activeAffiliates} active affiliate link${activeAffiliates > 1 ? 's' : ''} via /go/` : e.note }
+    : e);
   base.windowSums = led.windowSums;
   base.total = round(Object.values(led.byEngine).reduce((s, v) => s + v, 0), 2);
   return base;
@@ -870,7 +892,14 @@ const AUTH_PASS = process.env.ABRAMSEGO_PASS || 'DW2024!';
 // nothing in this repo sets it.
 const PUBLIC_LANDING = (process.env.PUBLIC_LANDING || '0') === '1';
 function isPublicLandingPath(req) {
-  if (req.method === 'GET') return req.path === '/landing' || req.path === '/landing.html' || req.path === '/api/sell/config';
+  if (req.method === 'GET') {
+    if (req.path === '/landing' || req.path === '/landing.html' || req.path === '/api/sell/config') return true;
+    // sample fleet-health report: canned demo data + SAMPLE watermark, never SNAP
+    if (req.path === '/api/report/sample') return true;
+    // affiliate surface: tracked redirects + the non-draft strip data (labels
+    // and slugs only — the registry's urls/notes stay behind auth).
+    return req.path.startsWith('/go/') || req.path === '/api/affiliates';
+  }
   if (req.method === 'POST') return req.path === '/api/waitlist';
   return false;
 }
@@ -1027,6 +1056,236 @@ app.post('/api/chat', async (req, res) => {
 const LANDING_FILE = path.join(__dirname, 'public', 'landing.html');
 app.get('/landing', (req, res) => res.sendFile(LANDING_FILE));
 
+// --- billable_work engine (engine 3): sellable Fleet Health Report ----------
+// The dashboard's own snapshot rendered as a polished, self-contained HTML
+// artifact a customer would pay for. /api/report/fleet-health = real data,
+// auth-gated like everything else. /api/report/sample = canned DEMO data with
+// a SAMPLE watermark, safe for the public landing allowlist — it never touches
+// SNAP, so no real fleet/cost internals can leak through it.
+const escHtml = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
+const fmtWhen = (iso) => {
+  if (!iso) return '—';
+  const d = new Date(iso);
+  return isNaN(d) ? '—' : d.toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' });
+};
+
+function renderFleetHealthReport(snap, { sample = false } = {}) {
+  const now = new Date();
+  const lf = snap.localFleet || {};
+  const kam = snap.kamatera || {};
+  const cans = (snap.canaries && snap.canaries.canaries) || [];
+  const cost = snap.cost || {};
+  const pnl = snap.pnl || {};
+  const sys = snap.system || {};
+  const money = (n) => n == null ? '—' : `$${round(Number(n) || 0, 2).toFixed(2)}`;
+
+  const fleetRows = (procs) => (procs || []).slice(0, 40).map((p) => `
+    <tr><td>${escHtml(p.name)}</td>
+      <td><span class="pill ${p.status === 'online' ? 'ok' : 'bad'}">${escHtml(p.status || 'unknown')}</span></td>
+      <td>${p.restarts == null ? '—' : escHtml(p.restarts)}</td>
+      <td title="${escHtml(p.startedAt || '')}">${fmtWhen(p.startedAt)}</td></tr>`).join('');
+
+  const canaryVerdictClass = (v) => /FAIL|DOWN|CRIT/i.test(v || '') ? 'bad' : /WARN|DEGRAD/i.test(v || '') ? 'warn' : v ? 'ok' : '';
+  const canaryRows = cans.slice(0, 30).map((c) => `
+    <tr><td>${escHtml(c.name)}</td>
+      <td><span class="pill ${canaryVerdictClass(c.verdict)}">${escHtml(c.verdict || 'n/a')}</span></td>
+      <td title="${escHtml(c.mtime || '')}">${fmtWhen(c.mtime)}</td>
+      <td>${c.stale ? '⚠️ stale' : 'fresh'}</td></tr>`).join('');
+
+  // 7-day cost trend as pure-CSS bars so the report stays one self-contained file
+  const series = cost.series7d || [];
+  const maxDay = Math.max(0.01, ...series.map((d) => d.total || 0));
+  const trendBars = series.map((d) => `
+    <div class="bar-col" title="${escHtml(d.day)}: $${d.total} (tokens $${d.tokens} + energy $${d.energy} est)">
+      <div class="bar" style="height:${Math.max(3, Math.round((d.total / maxDay) * 90))}px"></div>
+      <div class="bar-v">$${round(d.total, 2)}</div>
+      <div class="bar-d">${escHtml(String(d.day).slice(5))}</div>
+    </div>`).join('');
+
+  const pnlRows = ['today', 'week', 'month'].map((w) => {
+    const p = pnl[w] || {};
+    return `<tr><td>${w}</td><td>${money(p.cost)}</td><td>${money(p.revenue)}</td>
+      <td class="${(p.net || 0) >= 0 ? 'good' : 'red'}">${money(p.net)}</td>
+      <td>${p.selfFundingPct == null ? '—' : p.selfFundingPct + '%'}</td></tr>`;
+  }).join('');
+
+  const notes = [];
+  if (sys.dashboardUptimeSec != null) notes.push(`Command center itself has been up ${Math.floor(sys.dashboardUptimeSec / 3600)}h ${Math.floor((sys.dashboardUptimeSec % 3600) / 60)}m.`);
+  if (lf.note) notes.push(`Local fleet: ${lf.note}.`);
+  if (kam.note) notes.push(`Remote fleet: ${kam.note}.`);
+  const staleCans = cans.filter((c) => c.stale).length;
+  if (staleCans) notes.push(`${staleCans} canary heartbeat${staleCans > 1 ? 's are' : ' is'} >24h old — investigate before trusting their last verdicts.`);
+  const downProcs = [...(lf.procs || []), ...(kam.procs || [])].filter((p) => p.status && p.status !== 'online');
+  if (downProcs.length) notes.push(`Processes not online: ${downProcs.map((p) => p.name).slice(0, 10).join(', ')}.`);
+  if (!notes.length) notes.push('All monitored surfaces healthy at generation time.');
+
+  return `<!doctype html><html lang="en"><head><meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>AbramsEgo — Fleet Health Report</title>
+<style>
+  :root{--bg:#0c0e12;--panel:#14171d;--line:#242a33;--fg:#e8e6e0;--dim:#8a92a0;--gold:#d4a94f;--ok:#3fb96a;--warn:#d4a94f;--bad:#e0563f}
+  *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.55 -apple-system,'Helvetica Neue',Segoe UI,sans-serif}
+  .wrap{max-width:900px;margin:0 auto;padding:28px 22px 60px}
+  header{display:flex;align-items:center;gap:14px;border-bottom:1px solid var(--line);padding-bottom:18px;margin-bottom:22px;flex-wrap:wrap}
+  .logo{font-size:22px;letter-spacing:.4px}.logo b{color:var(--gold)}
+  .rtitle{font-size:13px;text-transform:uppercase;letter-spacing:2px;color:var(--dim)}
+  .price{margin-left:auto;background:var(--gold);color:#14120a;font-weight:700;border-radius:8px;padding:6px 14px;font-size:16px}
+  .when{color:var(--dim);font-size:13px;width:100%}
+  ${sample ? '.watermark{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;z-index:9}.watermark span{transform:rotate(-28deg);font-size:96px;font-weight:800;letter-spacing:10px;color:rgba(212,169,79,.07)}' : ''}
+  .banner{background:#2a2312;border:1px solid var(--gold);color:var(--gold);border-radius:8px;padding:8px 14px;font-size:13px;margin-bottom:20px}
+  section{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:18px 20px;margin-bottom:18px}
+  h2{margin:0 0 12px;font-size:16px;letter-spacing:.5px}h2 .k{color:var(--dim);font-weight:400;font-size:12px;margin-left:8px}
+  table{width:100%;border-collapse:collapse;font-size:13.5px}
+  th{color:var(--dim);text-align:left;font-weight:500;padding:4px 8px;border-bottom:1px solid var(--line);text-transform:uppercase;font-size:11px;letter-spacing:1px}
+  td{padding:5px 8px;border-bottom:1px solid #1b2027}tr:last-child td{border-bottom:0}
+  .pill{border-radius:20px;padding:1px 9px;font-size:11.5px;background:#20262f;color:var(--dim)}
+  .pill.ok{background:#14301e;color:var(--ok)}.pill.warn{background:#2f2711;color:var(--warn)}.pill.bad{background:#33170f;color:var(--bad)}
+  .good{color:var(--ok)}.red{color:var(--bad)}
+  .fleet-sum{display:flex;gap:26px;margin-bottom:12px;flex-wrap:wrap}
+  .fleet-sum .n{font-size:26px;font-weight:700}.fleet-sum .n.ok{color:var(--ok)}.fleet-sum .l{color:var(--dim);font-size:12px}
+  .trend{display:flex;align-items:flex-end;gap:10px;padding:8px 4px 0}
+  .bar-col{flex:1;text-align:center}.bar{background:linear-gradient(180deg,var(--gold),#8a6c2e);border-radius:4px 4px 0 0;margin:0 auto;width:70%}
+  .bar-v{font-size:10.5px;color:var(--dim);margin-top:4px}.bar-d{font-size:10.5px;color:var(--dim)}
+  ul{margin:6px 0 0;padding-left:20px}li{margin-bottom:5px}
+  footer{color:var(--dim);font-size:12px;text-align:center;margin-top:26px}
+</style></head><body>
+${sample ? '<div class="watermark"><span>SAMPLE</span></div>' : ''}
+<div class="wrap">
+<header>
+  <div class="logo"><b>Abrams</b>Ego</div>
+  <div class="rtitle">Fleet Health Report</div>
+  <div class="price">$${REPORT_PRICE_USD}</div>
+  <div class="when" title="${now.toISOString()}">🕓 Generated ${now.toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })}${sample ? ' · demo data' : ''}</div>
+</header>
+${sample ? '<div class="banner">SAMPLE REPORT — illustrative demo data. Your report is generated live from your own fleet.</div>' : ''}
+
+<section>
+  <h2>Fleet status<span class="k">local + remote process managers</span></h2>
+  <div class="fleet-sum">
+    <div><div class="n ${lf.up === lf.total ? 'ok' : ''}">${lf.up != null ? lf.up : '—'}/${lf.total != null ? lf.total : '—'}</div><div class="l">local processes online</div></div>
+    <div><div class="n ${kam.up === kam.total ? 'ok' : ''}">${kam.up != null ? kam.up : '—'}/${kam.total != null ? kam.total : '—'}</div><div class="l">remote (cloud) processes online</div></div>
+    <div><div class="n">${(snap.crons && snap.crons.loadedCount) != null ? snap.crons.loadedCount : '—'}</div><div class="l">scheduled jobs loaded</div></div>
+  </div>
+  <table><tr><th>process</th><th>status</th><th>restarts</th><th>🕓 started</th></tr>
+  ${fleetRows(lf.procs)}${fleetRows(kam.procs)}</table>
+</section>
+
+<section>
+  <h2>Canary verdicts<span class="k">health heartbeats across the fleet</span></h2>
+  ${canaryRows ? `<table><tr><th>canary</th><th>verdict</th><th>🕓 last heartbeat</th><th>freshness</th></tr>${canaryRows}</table>` : '<p class="l" style="color:var(--dim)">No canary heartbeats found.</p>'}
+</section>
+
+<section>
+  <h2>Cost trend · 7 days<span class="k">tokens + energy (est), per local calendar day</span></h2>
+  ${series.length ? `<div class="trend">${trendBars}</div>` : '<p style="color:var(--dim)">No cost series available.</p>'}
+</section>
+
+<section>
+  <h2>P&amp;L<span class="k">what the fleet costs vs what it earns</span></h2>
+  <table><tr><th>window</th><th>cost</th><th>revenue</th><th>net</th><th>self-funding</th></tr>${pnlRows}</table>
+  ${pnl.runwayNote ? `<p style="color:var(--dim);font-size:13px;margin:10px 0 0">${escHtml(pnl.runwayNote)}</p>` : ''}
+</section>
+
+<section>
+  <h2>Uptime notes</h2>
+  <ul>${notes.map((n) => `<li>${escHtml(n)}</li>`).join('')}</ul>
+</section>
+
+<footer>AbramsEgo · self-funding AI-agent command center · report price $${REPORT_PRICE_USD} · generated ${now.toISOString()}</footer>
+</div></body></html>`;
+}
+
+// Canned demo snapshot for the public sample — deliberately NOT derived from
+// SNAP so nothing real (process names, spend, canary names) can leak publicly.
+function demoReportData() {
+  const now = Date.now();
+  const iso = (msAgo) => new Date(now - msAgo).toISOString();
+  const day = (i) => {
+    const d = new Date(now - i * 24 * 3.6e6);
+    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
+  };
+  return {
+    system: { dashboardUptimeSec: 63 * 3600 + 12 * 60 },
+    localFleet: {
+      up: 5, total: 6,
+      procs: [
+        { name: 'agent-orchestrator', status: 'online', restarts: 0, startedAt: iso(52 * 3.6e6) },
+        { name: 'storefront-api', status: 'online', restarts: 1, startedAt: iso(30 * 3.6e6) },
+        { name: 'scraper-worker', status: 'online', restarts: 2, startedAt: iso(20 * 3.6e6) },
+        { name: 'image-pipeline', status: 'online', restarts: 0, startedAt: iso(76 * 3.6e6) },
+        { name: 'metrics-collector', status: 'online', restarts: 0, startedAt: iso(76 * 3.6e6) },
+        { name: 'batch-mailer', status: 'stopped', restarts: 4, startedAt: null },
+      ],
+    },
+    kamatera: {
+      up: 3, total: 3,
+      procs: [
+        { name: 'public-site', status: 'online', restarts: 0, startedAt: iso(200 * 3.6e6) },
+        { name: 'lead-api', status: 'online', restarts: 1, startedAt: iso(180 * 3.6e6) },
+        { name: 'cron-runner', status: 'online', restarts: 0, startedAt: iso(200 * 3.6e6) },
+      ],
+    },
+    crons: { loadedCount: 14 },
+    canaries: { canaries: [
+      { name: 'uptime-probe', verdict: 'PASS', mtime: iso(9 * 60e3), stale: false },
+      { name: 'backup-freshness', verdict: 'PASS', mtime: iso(3 * 3.6e6), stale: false },
+      { name: 'disk-space', verdict: 'WARN', mtime: iso(25 * 60e3), stale: false },
+      { name: 'price-integrity', verdict: 'PASS', mtime: iso(11 * 3.6e6), stale: false },
+      { name: 'leak-scanner', verdict: 'PASS', mtime: iso(30 * 3.6e6), stale: true },
+    ] },
+    cost: { series7d: [6, 5, 4, 3, 2, 1, 0].map((i, idx) => {
+      const tokens = [3.1, 4.6, 2.2, 5.8, 3.9, 4.4, 2.7][idx];
+      return { day: day(i), tokens, energy: 0.65, total: round(tokens + 0.65, 2) };
+    }) },
+    pnl: {
+      today: { cost: 3.35, revenue: 4.5, net: 1.15, selfFundingPct: 134.3 },
+      week: { cost: 26.4, revenue: 18.0, net: -8.4, selfFundingPct: 68.2 },
+      month: { cost: 104.9, revenue: 61.5, net: -43.4, selfFundingPct: 58.6 },
+      runwayNote: "Break-even needs $3.35/day ($100.50/mo). Today's revenue covers 134% of run cost — in the black.",
+    },
+  };
+}
+
+// Real report — sits behind the Basic-Auth middleware like every other route.
+app.get('/api/report/fleet-health', (req, res) => {
+  res.type('html').send(renderFleetHealthReport(SNAP));
+});
+// Public-safe sample (PUBLIC_LANDING allowlists it): demo data + watermark.
+app.get('/api/report/sample', (req, res) => {
+  res.type('html').send(renderFleetHealthReport(demoReportData(), { sample: true }));
+});
+
+// --- Affiliate engine (engine 2): tracked /go/:slug redirects ---------------
+// Registry-driven: data/affiliates.json maps slug → url. Every hit logs a
+// click row to data/affiliate-clicks.jsonl then 302s to the target. Drafts
+// redirect too (harmless — plain product pages) but only "active" entries are
+// exposed via /api/affiliates for the landing strip. No commission mechanism
+// exists here; Steve joining a program (and editing status→active) is the
+// gated switch that turns this into money.
+app.get('/go/:slug', (req, res) => {
+  const slug = (req.params.slug || '').toString().slice(0, 60);
+  const entry = readAffiliates().find((a) => a && a.slug === slug);
+  if (!entry || !entry.url) return res.status(404).json({ error: 'unknown affiliate slug' });
+  const row = {
+    ts: new Date().toISOString(),
+    slug,
+    ua: (req.headers['user-agent'] || '').toString().slice(0, 200),
+    ref: (req.headers.referer || '').toString().slice(0, 200),
+  };
+  try { fs.appendFileSync(AFFILIATE_CLICKS, JSON.stringify(row) + '\n'); } catch (e) {}
+  res.redirect(302, entry.url);
+});
+
+// Non-draft strip data for the landing "tools we run on" row. Public-safe:
+// labels + /go/ slugs only, and empty until Steve activates an entry — so
+// nothing customer-facing changes while the registry is all drafts.
+app.get('/api/affiliates', (req, res) => {
+  const active = readAffiliates()
+    .filter((a) => a && a.status && a.status !== 'draft')
+    .map((a) => ({ slug: a.slug, label: a.label }));
+  res.json({ count: active.length, affiliates: active });
+});
+
 // Waitlist email capture from the landing page → appends to data/waitlist.jsonl.
 // This is NOT a money mechanism — it only collects interest; no Stripe, no
 // charge, no send. One row per signup; basic email validation + dedupe-friendly.

← 16688f5 auto-save: 2026-07-01T17:37:49 (1 files) — data/local-fleet.  ·  back to AbramsEgo  ·  auto-save: 2026-07-01T18:07:58 (5 files) — build-queue/tasks 3dec20a →