← back to Rentv
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
M data/markets.jsonM data/news.jsonM data/ticker.jsonM server.js
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
·
auto-save: 2026-08-05T08:40:35 (3 files) — data/markets.json 9b0cf781 →