[object Object]

← back to Bertha

kalshi-dash: harden secrets + hook Gemini cost-tracker

db16b75173d6cd404c652946e8a2797e9f6c5602 · 2026-05-13 08:30:21 -0700 · Steve

- AUTH_PASS now required env var (fail-closed). Old literal in git history
  must be rotated.
- GEMINI_API_KEY moved to process.env.GEMINI_API_KEY (was broken literal
  '${GEMINI_API_KEY}' string from a prior incomplete refactor).
- Inline browser-side BasicAuth header removed — dashboard must use the
  server-side session cookie. Visible 401s on dashboard fetches until
  client refactor lands.
- geminiAnalyze() now logs every call to ~/.claude/cost-ledger.jsonl via
  the shared cost-tracker helper (app=kalshi-dash, note=ken-signal-analyze).

Files touched

Diff

commit db16b75173d6cd404c652946e8a2797e9f6c5602
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed May 13 08:30:21 2026 -0700

    kalshi-dash: harden secrets + hook Gemini cost-tracker
    
    - AUTH_PASS now required env var (fail-closed). Old literal in git history
      must be rotated.
    - GEMINI_API_KEY moved to process.env.GEMINI_API_KEY (was broken literal
      '${GEMINI_API_KEY}' string from a prior incomplete refactor).
    - Inline browser-side BasicAuth header removed — dashboard must use the
      server-side session cookie. Visible 401s on dashboard fetches until
      client refactor lands.
    - geminiAnalyze() now logs every call to ~/.claude/cost-ledger.jsonl via
      the shared cost-tracker helper (app=kalshi-dash, note=ken-signal-analyze).
---
 kalshi-dash/server.js | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/kalshi-dash/server.js b/kalshi-dash/server.js
index 88fc2dd..5189c25 100644
--- a/kalshi-dash/server.js
+++ b/kalshi-dash/server.js
@@ -15,8 +15,13 @@ const PORT = 7810;
 const DIST = path.join(__dirname, 'dist');
 
 // ── Unified DW Auth Config ──
-const AUTH_USER = 'admin';
-const AUTH_PASS = 'DWSecure2024!';
+// Audit 2026-05-04: fail-closed on missing env. Old literal `DWSecure2024!`
+// is now in source-control history and must be rotated.
+const AUTH_USER = process.env.AUTH_USERNAME || 'admin';
+const AUTH_PASS = process.env.AUTH_PASSWORD;
+if (!AUTH_PASS) {
+  throw new Error('AUTH_PASSWORD env var required (no fallback for production safety)');
+}
 const SESSION_COOKIE = 'kalshi_session';
 const SESSION_MAX_AGE = 30 * 24 * 60 * 60; // 30 days in seconds
 const WHITELISTED_IPS = ['127.0.0.1', '::1', '45.61.58.125', 'localhost'];
@@ -127,7 +132,10 @@ function bayesianUpdate(prior, forecastProb, weight = 0.7) {
 // ══════════════════════════════════════════════════════
 // GEMINI AI PREDICTION ENGINE — uses CPU + AI for better signals
 // ══════════════════════════════════════════════════════
-const GEMINI_API_KEY = 'AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo';
+// Audit 2026-05-04: literal AIzaSy… key removed from source. Now env-driven.
+// Previous in-source key needs rotation if still active. Fail-soft — when unset,
+// geminiAnalyze() returns null (handled downstream).
+const GEMINI_API_KEY = process.env.GEMINI_API_KEY || '';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 
 async function geminiAnalyze(prompt, maxTokens = 1024) {
@@ -149,6 +157,10 @@ async function geminiAnalyze(prompt, maxTokens = 1024) {
     clearTimeout(timeout);
     if (!res.ok) return null;
     const data = await res.json();
+    try {
+      const { logGemini } = require(require('os').homedir() + '/.claude/skills/cost-tracker/scripts/log-gemini.js');
+      logGemini(data, { app: 'kalshi-dash', note: 'ken-signal-analyze', model: GEMINI_MODEL });
+    } catch {}
     return data?.candidates?.[0]?.content?.parts?.[0]?.text || null;
   } catch (e) {
     console.log(`[Ken/Gemini] Error: ${e.message}`);
@@ -3543,8 +3555,13 @@ body::after{content:'';position:fixed;top:0;left:0;right:0;bottom:0;background-i
 <script type="text/babel">
 const { useState, useEffect, useRef } = React;
 
-const AUTH = btoa('admin:DWSecure2024!');
-const api = (url) => fetch(url, { headers: { 'Authorization': 'Basic ' + AUTH } }).then(r => r.json());
+// SECURITY (audit 2026-05-04): inline literal credentials shipped to every
+// browser via this <script> block. Removed. Dashboard MUST be refactored to
+// use the server-side session cookie (`kalshi_session`) for auth — the cookie
+// is already set on login and Express forwards it on subsequent requests.
+// Until refactor: dashboard fetches will 401 visibly, signaling the work needed.
+const AUTH = '';
+const api = (url) => fetch(url, { credentials: 'include' }).then(r => r.json());
 
 function Particles() {
   const particles = Array.from({ length: 30 }, (_, i) => ({

← 64afe10 untrack node_modules per standing rule (was tracking 12516 f  ·  back to Bertha  ·  snapshot: 11 file(s) changed, +3 new, ~2 modified, -6 remove 1b70167 →