← back to George Gmail
bridge: every-6-day 1-click renewal email to steve-office for the 2 consumer accounts (CADENCE mode) + dead-token safety net stays on 8/2/8
c4c9ba40f8a3096b860ec87369d1d9c4afc5c593 · 2026-07-15 12:17:27 -0700 · Steve
Files touched
A com.steve.george-token-cadence.plistM token-bridge.mjs
Diff
commit c4c9ba40f8a3096b860ec87369d1d9c4afc5c593
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jul 15 12:17:27 2026 -0700
bridge: every-6-day 1-click renewal email to steve-office for the 2 consumer accounts (CADENCE mode) + dead-token safety net stays on 8/2/8
---
com.steve.george-token-cadence.plist | 29 +++++++++++++++++++++++++++++
token-bridge.mjs | 25 +++++++++++++++++++------
2 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/com.steve.george-token-cadence.plist b/com.steve.george-token-cadence.plist
new file mode 100644
index 0000000..fbdcb31
--- /dev/null
+++ b/com.steve.george-token-cadence.plist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.steve.george-token-cadence</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/bin/sh</string>
+ <string>-c</string>
+ <string>/opt/homebrew/bin/node token-age-warn.mjs; CADENCE=1 /opt/homebrew/bin/node token-bridge.mjs</string>
+ </array>
+ <key>WorkingDirectory</key>
+ <string>/Users/macstudio3/Projects/george-gmail</string>
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>PATH</key>
+ <string>/opt/homebrew/bin:/usr/bin:/bin</string>
+ </dict>
+ <key>StartInterval</key>
+ <integer>518400</integer>
+ <key>RunAtLoad</key>
+ <false/>
+ <key>StandardOutPath</key>
+ <string>/Users/macstudio3/Library/Logs/george-token-cadence.log</string>
+ <key>StandardErrorPath</key>
+ <string>/Users/macstudio3/Library/Logs/george-token-cadence.log</string>
+</dict>
+</plist>
diff --git a/token-bridge.mjs b/token-bridge.mjs
index e8572fc..fdb4e8c 100644
--- a/token-bridge.mjs
+++ b/token-bridge.mjs
@@ -39,17 +39,30 @@ if (!latest || !Array.isArray(latest.accounts)) { console.log('[bridge] no lates
const state = load(STATE, {});
const now = Date.now();
-// Accounts needing a click: CRIT (dead) or WARN (aging past the horizon) AND that have a re-consent route.
-const need = latest.accounts.filter((a) => (a.level === 'CRIT' || a.level === 'WARN') && AUTH_ROUTE[a.key]);
-// Throttle: only re-nudge an account if we haven't in the last 20h.
-const due = need.filter((a) => now - (state[a.key]?.lastAlert || 0) > THROTTLE_MS);
-if (!due.length) { console.log(`[bridge] ${need.length} account(s) need renewal, 0 due to nudge (throttled)`); process.exit(0); }
+// Two modes:
+// • CADENCE=1 (the every-6-days job) → always send the two CONSUMER accounts' 1-click renew to
+// steve-office, regardless of exact age. Predictable "click every 6 days" rotation reminder.
+// • default (the 8/2/8 job) → SAFETY NET only: nudge accounts that have gone CRIT (dead) between
+// cadence runs, throttled, so an unexpected death still surfaces fast without routine spam.
+const CADENCE = process.env.CADENCE === '1';
+const CONSUMER = { PERSONAL_REFRESH_TOKEN: 'Steve Personal (@gmail)', AGENTABRAMS_REFRESH_TOKEN: 'Agent Abrams (@gmail)' };
+let due;
+if (CADENCE) {
+ due = Object.entries(CONSUMER).map(([key, label]) => {
+ const a = latest.accounts.find((x) => x.key === key) || {};
+ return { key, label, level: a.level === 'CRIT' ? 'CRIT' : 'renew', detail: a.detail || 'periodic 6-day renewal' };
+ });
+} else {
+ const need = latest.accounts.filter((a) => a.level === 'CRIT' && AUTH_ROUTE[a.key]);
+ due = need.filter((a) => now - (state[a.key]?.lastAlert || 0) > THROTTLE_MS);
+ if (!due.length) { console.log(`[bridge] safety-net: ${need.length} CRIT, 0 due (throttled)`); process.exit(0); }
+}
const base = GEORGE.replace(/\/$/, '');
const rows = due.map((a) => {
const url = `${base}/auth/${AUTH_ROUTE[a.key]}`;
- const tag = a.level === 'CRIT' ? '🔴 DEAD' : '🟠 expiring';
+ const tag = a.level === 'CRIT' ? '🔴 DEAD' : a.level === 'renew' ? '🔁 renew' : '🟠 expiring';
return `<tr><td style="padding:6px 12px 6px 0">${tag}</td><td style="padding:6px 12px 6px 0"><b>${a.label}</b><br><span style="color:#888;font-size:12px">${a.detail || ''}</span></td>`
+ `<td style="padding:6px 0"><a href="${url}" style="background:#8a6d3b;color:#fff;text-decoration:none;padding:7px 14px;border-radius:6px;font-weight:600">Renew now →</a></td></tr>`;
}).join('');
← a2eaa2d bridge: nudge to renew at day 5 (2-day runway before the 7-d
·
back to George Gmail
·
auto-save: 2026-07-15T12:36:34 (1 files) — data/bridge-alert a078db7 →