From adf5e6166d51276decaed3fe8bf3bb01149da832 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sat, 5 Sep 2026 16:54:23 -0600 Subject: [PATCH] add a flag for the debug endpoints, and distinguish unavailable errors --- .env.example | 4 ++++ src/env.ts | 12 ++++++++++++ src/index.ts | 8 ++++++-- src/middleware/auth.ts | 5 +++-- src/services/endorserClient.ts | 6 +++--- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index cb6b79d..ea4addf 100644 --- a/.env.example +++ b/.env.example @@ -21,3 +21,7 @@ PORT=3003 # Do not set NODE_ENV=test-local in production (bypasses ethr JWT expiry). # NODE_ENV=test-local + +# Mount the /debug router (device lookup, manual wakeup send). Default: false. +# Leave off in production; the routes expose per-device state to any accepted JWT. +# DEBUG_ENDPOINT=false diff --git a/src/env.ts b/src/env.ts index 3e3cce2..d49fe5c 100644 --- a/src/env.ts +++ b/src/env.ts @@ -19,3 +19,15 @@ export const PARTNER_URL = process.env.PARTNER_URL ?? process.env.DEFAULT_PARTNER_API_SERVER ?? DEFAULT_PARTNER_API_SERVER; + +/** Truthy env values for boolean flags: "true"/"1"/"yes"/"on" (case-insensitive). */ +function envFlag(value: string | undefined, fallback: boolean): boolean { + if (value === undefined || value.trim().length === 0) return fallback; + const normalized = value.trim().toLowerCase(); + if (["true", "1", "yes", "on"].includes(normalized)) return true; + if (["false", "0", "no", "off"].includes(normalized)) return false; + return fallback; +} + +/** Mounts /debug when true. Off unless explicitly enabled. */ +export const DEBUG_ENDPOINT = envFlag(process.env.DEBUG_ENDPOINT, false); diff --git a/src/index.ts b/src/index.ts index 6531691..4ef3b0b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import "./env.js"; import cors from "cors"; import express from "express"; import "./services/firebase.js"; +import { DEBUG_ENDPOINT } from "./env.js"; import { debugRouter } from "./routes/debug.js"; import { notificationsRouter } from "./routes/notifications.js"; import { startAlertSearchScheduler } from "./alertSearch/scheduler.js"; @@ -27,8 +28,11 @@ app.get("/health", (_req, res) => { app.use("/notifications", notificationsRouter); -// Only include on test environments -// app.use("/debug", debugRouter); +// Only include on test environments (DEBUG_ENDPOINT=true) +if (DEBUG_ENDPOINT) { + app.use("/debug", debugRouter); + console.log("* Debug endpoints enabled at /debug (DEBUG_ENDPOINT=true)"); +} startScheduler(); startAlertSearchScheduler(); diff --git a/src/middleware/auth.ts b/src/middleware/auth.ts index db38442..75ab8eb 100644 --- a/src/middleware/auth.ts +++ b/src/middleware/auth.ts @@ -141,12 +141,13 @@ export async function requireEndorserAuth( const errorTime = new Date().toISOString(); const did = req.did ?? "(unknown)"; - if (result.reason === "unavailable") { + if (result.reason !== "unauthorized") { console.log("[Auth] Endorser unavailable"); console.error( "[Auth] Endorser auth check unavailable at", errorTime + ", did:", - did + did + ", reason:", + result.reason ); res.status(503).json({ success: false, diff --git a/src/services/endorserClient.ts b/src/services/endorserClient.ts index 2179bb0..256fb4e 100644 --- a/src/services/endorserClient.ts +++ b/src/services/endorserClient.ts @@ -5,7 +5,7 @@ const RATE_LIMITS_PATH = "/api/report/rateLimits"; export type EndorserAuthResult = | { ok: true } - | { ok: false; reason: "unauthorized" | "unavailable" }; + | { ok: false; reason: "unauthorized" | "unavailable error" | "unavailable 500" }; function rateLimitsUrl(): string { const base = ENDORSER_URL.replace(/\/+$/, ""); @@ -36,7 +36,7 @@ export async function checkAuth(jwt: string): Promise { url + ":", errorMessage(err) ); - return { ok: false, reason: "unavailable" }; + return { ok: false, reason: "unavailable error" }; } if (response.ok) { @@ -50,7 +50,7 @@ export async function checkAuth(jwt: string): Promise { url + ", status", response.status ); - return { ok: false, reason: "unavailable" }; + return { ok: false, reason: "unavailable 500" }; } // 4xx: JWT rejected or user not registered on Endorser.