From 73ec7f1436fab0b280a8e485e8a756116dad8b2e Mon Sep 17 00:00:00 2001 From: Waters Church Date: Thu, 24 Sep 2026 13:04:46 -0400 Subject: [PATCH] Report the app version on /healthz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build 116. /healthz has always carried a 'build' field, but it is a hash of the listener page's assets — a cache-busting token, not a version. So the only way to tell what a campus Mac was actually running was to install something and watch the hash move, which is how the last three updates were confirmed. With an updater in the field, what version a machine is on is the first question anyone asks. It now answers plainly: version and buildNumber, passed to the server child from the running bundle. Checking a campus is a single unauthenticated request. It found something immediately: this development Mac reported appBuild 112 while the source tree was at 115, because deploying loose files over an installed bundle leaves its package.json behind. A packaged install reports correctly. Co-Authored-By: Claude Opus 5 --- app/main.js | 5 +++++ app/package.json | 4 ++-- app/server/server.js | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/main.js b/app/main.js index 701849b..4ac47ed 100644 --- a/app/main.js +++ b/app/main.js @@ -440,6 +440,11 @@ function startServer() { execPath: nodeBin, env: Object.assign({}, process.env, { CT_FFMPEG: ffmpegPathForChildren(), + /* So /healthz can report the APP’s version rather than only an asset + hash. A campus Mac’s build was otherwise unknowable from the network, + which made confirming an update a matter of inference. */ + CT_APP_VERSION: appBuild().version, + CT_APP_BUILD: appBuild().build, PORT: String(port), DATA_DIR: dataDir(), /* Where the spoken clips land, so the server can hand them to phones. */ diff --git a/app/package.json b/app/package.json index 7e58b43..8e6ff91 100644 --- a/app/package.json +++ b/app/package.json @@ -2,7 +2,7 @@ "name": "church-translate-engine", "productName": "Church Translate", "version": "3.23.2", - "buildNumber": 115, + "buildNumber": 116, "private": true, "description": "Live sermon translation — self-contained: captures audio, transcribes, translates, and serves the congregation page itself", "main": "main.js", @@ -106,7 +106,7 @@ ] }, "asar": false, - "buildVersion": "115", + "buildVersion": "116", "win": { "target": [ { diff --git a/app/server/server.js b/app/server/server.js index 2c51504..ab5083d 100644 --- a/app/server/server.js +++ b/app/server/server.js @@ -1095,7 +1095,22 @@ const server = http.createServer(async (req, res) => { } if (req.method === 'OPTIONS') { res.writeHead(origin ? 204 : 405).end(); return; } - if (p === '/healthz') { sendJSON(res, 200, { ok: true, live: state.live, build: BUILD }); return; } + /* + * The APP's version, plainly, to anyone who can reach this port. + * + * `build` here has always been a hash of the listener-page assets — a + * cache-busting token, not a version — so the only way to tell what a campus + * Mac was running was to install something and watch the hash move. With an + * updater in the field that is the first question anyone asks, so answer it. + */ + if (p === '/healthz') { + sendJSON(res, 200, { + ok: true, live: state.live, build: BUILD, + version: process.env.CT_APP_VERSION || '', + appBuild: process.env.CT_APP_BUILD || '' + }); + return; + } // --- Companion / Stream Deck control ------------------------------- // GET or POST, token in ?key= or the X-Control-Token header.