← back to Dw Signup Fulfillment
TK-11120: server.js baseUrl() also fails closed on missing PUBLIC_URL (defense-in-depth)
52afecd00f65f9859dd5525eadc12a1a1f56b556 · 2026-09-02 14:01:55 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017j4qS38tWq21qYdjxMcFTy
Files touched
Diff
commit 52afecd00f65f9859dd5525eadc12a1a1f56b556
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Sep 2 14:01:55 2026 -0700
TK-11120: server.js baseUrl() also fails closed on missing PUBLIC_URL (defense-in-depth)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017j4qS38tWq21qYdjxMcFTy
---
server.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/server.js b/server.js
index 98ddf8b..1b32382 100644
--- a/server.js
+++ b/server.js
@@ -214,7 +214,13 @@ app.get('/verify', async (req, res) => {
});
// Public base the emailed Approve/Reject buttons point at (Kamatera host at go-live).
-function baseUrl() { return config.PUBLIC_URL || `http://127.0.0.1:${config.PORT}`; }
+// FAIL-CLOSED in LIVE (TK-11120): never fall back to the loopback host in a real send —
+// a localhost link mailed to a human is dead. Only DRY_RUN/dev may use the loopback base.
+function baseUrl() {
+ if (config.PUBLIC_URL) return config.PUBLIC_URL;
+ if (config.DRY_RUN) return `http://127.0.0.1:${config.PORT}`;
+ return '';
+}
// Send the trade-application review card to the office inbox via George.
async function notifyTradeApplication(application) {
← a6edf22 TK-11120: corrected resend tool + apology template (retail-v
·
back to Dw Signup Fulfillment
·
auto-data-snapshot: 2026-09-02T14:03:59 (1 data files) — ver e288df7 →