← back to CelebritySignatures
Live-mode switch (prep for go-live, defaults OFF): STRIPE_LIVE used ONLY when STRIPE_LIVE_ENABLED=1 AND sk_live_ present — else test. Real cards never charged unless Steve explicitly flips both. Generalized cs_(test|live)_ session-id checks. Boot logs the active mode (TK-10181)
cc656ee8bd0e532fdb56ba6b9857fef36bc6b913 · 2026-08-04 10:27:09 -0700 · Steve Abrams
Files touched
Diff
commit cc656ee8bd0e532fdb56ba6b9857fef36bc6b913
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Aug 4 10:27:09 2026 -0700
Live-mode switch (prep for go-live, defaults OFF): STRIPE_LIVE used ONLY when STRIPE_LIVE_ENABLED=1 AND sk_live_ present — else test. Real cards never charged unless Steve explicitly flips both. Generalized cs_(test|live)_ session-id checks. Boot logs the active mode (TK-10181)
---
server.js | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/server.js b/server.js
index a25a670..b3855bd 100644
--- a/server.js
+++ b/server.js
@@ -47,17 +47,25 @@ function readBodyBig(req) {
// which appends a commission entry to data/download-ledger.jsonl per download.
const UPLOADS_DIR = join(DATA, 'uploads-private');
const LB_HITS = new Map(); // per-IP leaderboard POST timestamps (rate limit)
-// Stripe TEST key ONLY (sk_test_…). We deliberately never read a live key here —
-// going live is a separate Steve-gated switch. Load from env or the project .env.
-function stripeTestKey() {
- if (process.env.STRIPE_TEST_SECRET_KEY) return process.env.STRIPE_TEST_SECRET_KEY;
+// Stripe key resolver. TEST by default. LIVE (real money) is used ONLY when
+// BOTH STRIPE_LIVE_ENABLED=1 AND a sk_live_ key are present — the deliberate
+// Steve-gated go-live switch. Default (flag unset) = test mode, so real cards
+// are never charged unless Steve explicitly turns it on.
+function envVal(name) {
+ if (process.env[name]) return process.env[name];
try {
- const m = readFileSync(new URL('.env', import.meta.url), 'utf8').match(/^STRIPE_TEST_SECRET_KEY=(.+)$/m);
+ const m = readFileSync(new URL('.env', import.meta.url), 'utf8').match(new RegExp('^' + name + '=(.+)$', 'm'));
if (m) return m[1].trim().replace(/^["']|["']$/g, '');
} catch {}
return null;
}
-const STRIPE_TEST_KEY = (() => { const k = stripeTestKey(); return k && k.startsWith('sk_test_') ? k : null; })();
+const STRIPE_LIVE_ENABLED = envVal('STRIPE_LIVE_ENABLED') === '1';
+const _testKey = (() => { const k = envVal('STRIPE_TEST_SECRET_KEY'); return k && k.startsWith('sk_test_') ? k : null; })();
+const _liveKey = (() => { const k = envVal('STRIPE_LIVE_SECRET_KEY'); return k && k.startsWith('sk_live_') ? k : null; })();
+const STRIPE_LIVE = STRIPE_LIVE_ENABLED && _liveKey; // real-money mode active?
+const STRIPE_TEST_KEY = STRIPE_LIVE ? _liveKey : _testKey; // the key the endpoints use
+const STRIPE_MODE = STRIPE_LIVE ? 'live' : 'test';
+if (STRIPE_LIVE) console.log('⚠️ STRIPE LIVE MODE — real charges enabled'); else if (_testKey) console.log('Stripe test mode active');
// Atomic in-process guard against concurrent double-credit for the same paid session
// (claimed synchronously before any await; the download-ledger is the restart-surviving backstop).
const USED_SIDS = new Set();
@@ -309,7 +317,7 @@ createServer(async (req, res) => {
if (path === '/order-success' && M === 'GET') {
const sid = url.searchParams.get('sid') || '';
let paid = false, order = null;
- if (STRIPE_TEST_KEY && /^cs_test_[A-Za-z0-9]+$/.test(sid)) {
+ if (STRIPE_TEST_KEY && /^cs_(test|live)_[A-Za-z0-9]+$/.test(sid)) {
try {
const s = await (await fetch(`https://api.stripe.com/v1/checkout/sessions/${sid}`, { headers: { Authorization: `Bearer ${STRIPE_TEST_KEY}` } })).json();
if (s.payment_status === 'paid') {
@@ -422,7 +430,7 @@ ${paid ? `<div class="ok">✓</div><h1>Order confirmed</h1>
// PAYMENT GATE (TEST mode): require a PAID Stripe checkout session for this file.
const sid = url.searchParams.get('sid') || '';
if (!STRIPE_TEST_KEY) return sendJSON(res, 503, { ok: false, error: 'downloads require payment — not configured yet' });
- if (!/^cs_test_[A-Za-z0-9]+$/.test(sid)) return sendJSON(res, 402, { ok: false, error: 'payment required — purchase this download first', purchase: '/api/signature-checkout' });
+ if (!/^cs_(test|live)_[A-Za-z0-9]+$/.test(sid)) return sendJSON(res, 402, { ok: false, error: 'payment required — purchase this download first', purchase: '/api/signature-checkout' });
let paid = false, sessionCreated = 0;
try {
const s = await (await fetch(`https://api.stripe.com/v1/checkout/sessions/${sid}`, { headers: { Authorization: `Bearer ${STRIPE_TEST_KEY}` } })).json();
← d8cfb50 SECURITY (HOLE 5, blocks live money): paid download link no
·
back to CelebritySignatures
·
Live switch is now MURAL-ONLY (Steve go-live 2026-08-04): pe ea2f10b →