← back to Butlr
callback_phone: use BUTLR_OWNER_CALLBACK_PHONE env + per-call override
06f6cc8ef8accc11f608b07b236ed9b4ddbe9a5a · 2026-05-14 09:28:40 -0700 · SteveStudio2
Per Steve's standing instruction (2026-05-14): Bridge-me-now should dial
the human's personal cell, NOT the Twilio outbound FROM line. The
quick-dial handler was reading req.user.email_phone, a field that does
not exist in users.js's schema, falling all the way through to the
hardcoded +16067130489 (the Twilio FROM number).
Fix has two halves:
1. seedLegacyAdmin() now persists callback_phone from a new env var
BUTLR_OWNER_CALLBACK_PHONE so every fresh boot picks it up.
2. /api/quick-dial's callback chain becomes:
body.callback_phone (per-call override from /butlr skill)
→ req.user.callback_phone (seeded from env)
→ process.env.BUTLR_OWNER_CALLBACK_PHONE
→ process.env.TWILIO_PHONE_NUMBER (last-resort fallback)
→ +16067130489
Steve set BUTLR_OWNER_CALLBACK_PHONE=+13107130489 in /root/public-projects/butlr/.env
and pm2-restarts butlr, the admin user record auto-persists callback_phone.
Files touched
M lib/users.jsM routes/public.js
Diff
commit 06f6cc8ef8accc11f608b07b236ed9b4ddbe9a5a
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Thu May 14 09:28:40 2026 -0700
callback_phone: use BUTLR_OWNER_CALLBACK_PHONE env + per-call override
Per Steve's standing instruction (2026-05-14): Bridge-me-now should dial
the human's personal cell, NOT the Twilio outbound FROM line. The
quick-dial handler was reading req.user.email_phone, a field that does
not exist in users.js's schema, falling all the way through to the
hardcoded +16067130489 (the Twilio FROM number).
Fix has two halves:
1. seedLegacyAdmin() now persists callback_phone from a new env var
BUTLR_OWNER_CALLBACK_PHONE so every fresh boot picks it up.
2. /api/quick-dial's callback chain becomes:
body.callback_phone (per-call override from /butlr skill)
→ req.user.callback_phone (seeded from env)
→ process.env.BUTLR_OWNER_CALLBACK_PHONE
→ process.env.TWILIO_PHONE_NUMBER (last-resort fallback)
→ +16067130489
Steve set BUTLR_OWNER_CALLBACK_PHONE=+13107130489 in /root/public-projects/butlr/.env
and pm2-restarts butlr, the admin user record auto-persists callback_phone.
---
lib/users.js | 7 +++++++
routes/public.js | 10 +++++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/lib/users.js b/lib/users.js
index 2ffccd6..4bad7e2 100644
--- a/lib/users.js
+++ b/lib/users.js
@@ -160,12 +160,18 @@ function seedLegacyAdmin() {
u.owner_token_sha256 && u.owner_token_sha256 === sha256(legacyToken));
if (existing) return existing;
+ // Optional — pick up a personal callback phone from env so Bridge-me-now
+ // dials the human, not the Twilio FROM line. Used by the /api/quick-dial
+ // path. Independent of TWILIO_PHONE_NUMBER (which is the outbound FROM).
+ const callbackPhone = (process.env.BUTLR_OWNER_CALLBACK_PHONE || '').trim() || null;
+
// If an admin with this email already exists, rotate their token to match.
const byEmail = all.find(u => normalizeEmail(u.email) === normalizeEmail(legacyEmail));
if (byEmail) {
byEmail.owner_token = legacyToken;
byEmail.owner_token_sha256 = sha256(legacyToken);
byEmail.role = 'admin';
+ if (callbackPhone) byEmail.callback_phone = callbackPhone;
writeAllAtomic(all);
return byEmail;
}
@@ -179,6 +185,7 @@ function seedLegacyAdmin() {
owner_token: legacyToken,
owner_token_sha256: sha256(legacyToken),
role: 'admin',
+ callback_phone: callbackPhone,
created_at: new Date().toISOString(),
last_login_at: null,
legacy_seeded: true,
diff --git a/routes/public.js b/routes/public.js
index 33d81c7..abeafd5 100644
--- a/routes/public.js
+++ b/routes/public.js
@@ -205,7 +205,15 @@ router.post('/api/quick-dial', express.urlencoded({ extended: true }), async (re
business_name: body.business_name,
business_phone: body.business_phone,
goal: body.goal,
- callback_phone: req.user.email_phone || process.env.TWILIO_PHONE_NUMBER || '+16067130489',
+ // callback_phone is the number Twilio dials for Bridge-me-now — should
+ // be the human's personal cell, NOT the Twilio outbound FROM line.
+ // Body override > user record > BUTLR_OWNER_CALLBACK_PHONE env > Twilio
+ // FROM (last-resort, will mean Bridge-me-now dials the Twilio line).
+ callback_phone: (body.callback_phone || '').trim()
+ || req.user.callback_phone
+ || process.env.BUTLR_OWNER_CALLBACK_PHONE
+ || process.env.TWILIO_PHONE_NUMBER
+ || '+16067130489',
callback_name: (req.user.email || '').split('@')[0] || 'You',
callback_email: req.user.email || '',
category: body.category || 'other',
← 25f76be Add /api/runtime-config — surfaces DRY_RUN state for the /bu
·
back to Butlr
·
Add password-reset token store, pluggable delivery layer, an 051c322 →