[object Object]

← back to Rentv 2026

auto-save: 2026-08-05T08:10:17 (4 files) — data/markets.json data/news.json data/ticker.json server.js

b4364477ccbba577681801d40c6c3b3c0e0fd83e · 2026-08-05 08:10:18 -0700 · Steve Abrams

Files touched

Diff

commit b4364477ccbba577681801d40c6c3b3c0e0fd83e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 5 08:10:18 2026 -0700

    auto-save: 2026-08-05T08:10:17 (4 files) — data/markets.json data/news.json data/ticker.json server.js
---
 data/markets.json | 20 ++++++++++----------
 data/news.json    |  2 +-
 data/ticker.json  | 12 ++++++------
 server.js         | 10 ++++++----
 4 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/data/markets.json b/data/markets.json
index 49f55838..3c9e3cf9 100644
--- a/data/markets.json
+++ b/data/markets.json
@@ -1,5 +1,5 @@
 {
-  "fetched_at": "2026-08-05T14:34:00.012Z",
+  "fetched_at": "2026-08-05T14:54:00.853Z",
   "source": "Yahoo Finance — live (CBOE Treasury yields, Dow Jones/MSCI REIT indices)",
   "curve": [
     {
@@ -11,14 +11,14 @@
     {
       "label": "5-Year",
       "value": "4.34%",
-      "change_bps": 0,
-      "dir": "flat"
+      "change_bps": 1,
+      "dir": "up"
     },
     {
       "label": "10-Year",
-      "value": "4.62%",
-      "change_bps": -1,
-      "dir": "down"
+      "value": "4.63%",
+      "change_bps": 0,
+      "dir": "flat"
     },
     {
       "label": "30-Year",
@@ -42,8 +42,8 @@
   "reits": [
     {
       "label": "DJ U.S. Real Estate",
-      "value": "395.03",
-      "change_pct": -0.27,
+      "value": "392.90",
+      "change_pct": -0.81,
       "dir": "down"
     },
     {
@@ -54,8 +54,8 @@
     },
     {
       "label": "Vanguard REIT ETF (VNQ)",
-      "value": "$98.70",
-      "change_pct": -0.37,
+      "value": "$98.19",
+      "change_pct": -0.89,
       "dir": "down"
     }
   ],
diff --git a/data/news.json b/data/news.json
index 502964ec..0ad2a505 100644
--- a/data/news.json
+++ b/data/news.json
@@ -1,6 +1,6 @@
 {
  "source": "rentv.com — live",
- "fetched_at": "2026-08-05T14:33:59.762Z",
+ "fetched_at": "2026-08-05T14:54:00.583Z",
  "count": 30,
  "items": [
   {
diff --git a/data/ticker.json b/data/ticker.json
index 3b6dca25..0f5b0948 100644
--- a/data/ticker.json
+++ b/data/ticker.json
@@ -1,5 +1,5 @@
 {
-  "fetched_at": "2026-08-05T14:33:59.983Z",
+  "fetched_at": "2026-08-05T14:54:00.825Z",
   "la_office_vac": {
     "label": "LA OFFICE VAC",
     "value": "23.1%",
@@ -14,16 +14,16 @@
   },
   "cre_index": {
     "label": "CRE INDEX",
-    "value": "4,152",
-    "change_pct": -0.27,
+    "value": "4,129",
+    "change_pct": -0.81,
     "dir": "down",
     "source": "Dow Jones U.S. Real Estate"
   },
   "ten_yr": {
     "label": "10-YR",
-    "value": "4.62%",
-    "change_bps": -1,
-    "dir": "down",
+    "value": "4.63%",
+    "change_bps": 0,
+    "dir": "flat",
     "source": "CBOE 10-Yr (^TNX)"
   }
 }
\ No newline at end of file
diff --git a/server.js b/server.js
index 66e373c9..87ca2ff2 100644
--- a/server.js
+++ b/server.js
@@ -502,12 +502,14 @@ app.post('/api/content/find-image', adminOnly, async (req, res) => {
 // ── Content Studio: email the full assembled post to Boom via George ────────────
 const GEORGE_URL = process.env.GEORGE_URL || 'http://127.0.0.1:9850';
 const GEORGE_BASIC_AUTH = process.env.GEORGE_BASIC_AUTH || '';
-const GEORGE_AUTH = process.env.GEORGE_AUTH || ''; // local :9850 app expects the raw Authorization token
-const GEORGE_HDR = GEORGE_AUTH || (GEORGE_BASIC_AUTH ? 'Basic ' + GEORGE_BASIC_AUTH : '');
+// George uses Basic auth; sbloom@rentv.com is EXTERNAL so George also needs the human-approval
+// token in the X-Send-Approval header (else it fail-closed blocks the send).
+const GEORGE_HDR = GEORGE_BASIC_AUTH ? 'Basic ' + GEORGE_BASIC_AUTH : '';
+const GEORGE_SEND_APPROVAL = process.env.GEORGE_EXTERNAL_SEND_TOKEN || '';
 const BOOM_EMAIL = process.env.BOOM_EMAIL || 'sbloom@rentv.com';
 app.post('/api/content/email', adminOnly, async (req, res) => {
   const b = req.body || {};
-  if (!GEORGE_HDR) return res.status(503).json({ ok: false, error: 'email not configured (GEORGE_AUTH/GEORGE_BASIC_AUTH missing)' });
+  if (!GEORGE_HDR) return res.status(503).json({ ok: false, error: 'email not configured (GEORGE_BASIC_AUTH missing)' });
   const title = clean(b.title, 200) || 'RENTV post';
   const html = `<h1>${clean(b.title, 200)}</h1>${b.dek ? `<p><em>${clean(b.dek, 300)}</em></p>` : ''}`
     + (b.image ? `<p><img src="${clean(b.image, 500)}" style="max-width:100%"><br><small>Photo: ${clean(b.photo_credit, 160) || '—'}</small></p>` : '')
@@ -516,7 +518,7 @@ app.post('/api/content/email', adminOnly, async (req, res) => {
     + (b.x ? `<h3>X</h3><p>${clean(b.x, 600)}</p>` : '');
   try {
     const r = await fetch(GEORGE_URL + '/api/send', {
-      method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: GEORGE_HDR },
+      method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: GEORGE_HDR, ...(GEORGE_SEND_APPROVAL ? { 'X-Send-Approval': GEORGE_SEND_APPROVAL } : {}) },
       body: JSON.stringify({ account: 'steve-office', to: BOOM_EMAIL, subject: 'RENTV draft: ' + title, body: html }),
       signal: AbortSignal.timeout(25000),
     });

← 70045f71 Content Studio email: use raw GEORGE_AUTH token for local Ge  ·  back to Rentv 2026  ·  auto-save: 2026-08-05T08:40:35 (3 files) — data/markets.json 9b0cf781 →