[object Object]

← back to Butlr

Add /api/runtime-config — surfaces DRY_RUN state for the /butlr skill

25f76bedfe948f67ab5149b25fe4ef07ef62d2c4 · 2026-05-14 08:52:53 -0700 · SteveStudio2

The /butlr Claude Code skill was confidently saying 'DIALED' when the
server was actually in TWILIO_DRY_RUN=ON mode (simulated state machine,
no real Twilio call). The skill now hits this probe BEFORE POSTing to
/api/quick-dial; if dry_run is true it warns Steve and refuses to
claim 'DIALED' without explicit override.

Owner-only. Surfaces nothing sensitive — only boolean flags.

Files touched

Diff

commit 25f76bedfe948f67ab5149b25fe4ef07ef62d2c4
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Thu May 14 08:52:53 2026 -0700

    Add /api/runtime-config — surfaces DRY_RUN state for the /butlr skill
    
    The /butlr Claude Code skill was confidently saying 'DIALED' when the
    server was actually in TWILIO_DRY_RUN=ON mode (simulated state machine,
    no real Twilio call). The skill now hits this probe BEFORE POSTing to
    /api/quick-dial; if dry_run is true it warns Steve and refuses to
    claim 'DIALED' without explicit override.
    
    Owner-only. Surfaces nothing sensitive — only boolean flags.
---
 routes/public.js | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/routes/public.js b/routes/public.js
index f25ef37..33d81c7 100644
--- a/routes/public.js
+++ b/routes/public.js
@@ -471,4 +471,21 @@ router.get('/social-claim', (req, res) => {
 
 router.get('/healthz', (req, res) => res.type('text').send('ok'));
 
+// Owner-only runtime-config probe — used by the /butlr Claude Code skill
+// to detect DRY_RUN mode before claiming "DIALED". Surfaces nothing
+// sensitive (no creds, no token last4) — only the boolean flags that
+// determine whether a real Twilio dial will actually happen.
+router.get('/api/runtime-config', (req, res) => {
+  if (!req.user) return res.status(401).json({ ok: false, error: 'unauthorized' });
+  res.json({
+    ok: true,
+    twilio_dry_run: process.env.TWILIO_DRY_RUN !== '0',
+    twilio_configured: !!(process.env.TWILIO_ACCOUNT_SID &&
+      (process.env.TWILIO_AUTH_TOKEN ||
+        (process.env.TWILIO_API_KEY_SID && process.env.TWILIO_API_KEY_SECRET))),
+    twilio_from_set: !!process.env.TWILIO_PHONE_NUMBER,
+    stripe_dry_run: process.env.STRIPE_DRY_RUN !== '0',
+  });
+});
+
 module.exports = router;

← 89f3440 owner-auth: accept token via X-Butlr-Owner-Token header + Be  ·  back to Butlr  ·  callback_phone: use BUTLR_OWNER_CALLBACK_PHONE env + per-cal 06f6cc8 →