← back to Marketing Command Center
channels: three-valued is_valid guard so a Graph rate-limit/error can't false-flip a valid Meta token to needsReconnect
f872cf0bc78c77c363447667133696dfc858ccc3 · 2026-07-14 13:12:23 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Files touched
M modules/channels/index.js
Diff
commit f872cf0bc78c77c363447667133696dfc858ccc3
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 14 13:12:23 2026 -0700
channels: three-valued is_valid guard so a Graph rate-limit/error can't false-flip a valid Meta token to needsReconnect
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
modules/channels/index.js | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/modules/channels/index.js b/modules/channels/index.js
index c69a918..03fd2bf 100644
--- a/modules/channels/index.js
+++ b/modules/channels/index.js
@@ -293,12 +293,21 @@ async function metaTokenHealth() {
try {
const r = await fetch(`${GRAPH}/debug_token?input_token=${encodeURIComponent(token)}&access_token=${encodeURIComponent(appId + '|' + secret)}`);
const j = await r.json().catch(() => ({}));
- const d = j.data || {};
+ // Graph signals rate-limits / app-token problems as a TOP-LEVEL {error} (no
+ // throw, no data.is_valid) — that means we COULDN'T verify, not that the user
+ // token is bad. Treat is_valid as three-valued: only a definitive boolean
+ // false flips a token; a missing/indeterminate verdict → ok:null (unknown),
+ // leaving the presence-based status untouched (fail-safe).
+ if (j.error || !j.data || typeof j.data.is_valid !== 'boolean') {
+ const v = { present: true, ok: null, reason: j.error?.message || 'validity indeterminate — Graph returned no verdict' };
+ _metaHealth = { token, at: now, v }; return v;
+ }
+ const d = j.data;
const v = {
present: true,
- ok: d.is_valid === true,
+ ok: d.is_valid,
expiresAt: d.expires_at ? d.expires_at * 1000 : null,
- reason: d.error?.message || (d.is_valid === false ? 'token invalid/expired' : null),
+ reason: d.is_valid ? null : (d.error?.message || 'token invalid/expired'),
};
_metaHealth = { token, at: now, v }; return v;
} catch (e) { // network failure → unknown, keep prior belief
← c60d8ff Expand Sounds catalog: +6 royalty-free libraries & SFX, live
·
back to Marketing Command Center
·
chore: lint fixes (jget r.ok guard, .env value quoting per u df1e623 →