[object Object]

← back to Site Factory

sf-orchestrator: unwedge from May-7 schema-missing freeze

1b587d34d530e7a5cb89cea6734b6451cd6ce9c0 · 2026-05-19 21:10:52 -0700 · SteveStudio2

- apply db/schema.sql (palettes/sites/stages/manager_findings/actions_log/analytics_events all missing)
- seed 20 fashion-house palettes via scripts/seed-palettes.js
- add global error middleware + express-async-errors so async pg throws no longer leave responses hanging
- wire BASIC_AUTH into ecosystem.config.js env (was unset → process.exit(1) on every restart → max-restart kill → silent absence)
- smoke: GET /health 200, GET /sites {sites:[]}, GET /palettes count=20

Files touched

Diff

commit 1b587d34d530e7a5cb89cea6734b6451cd6ce9c0
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Tue May 19 21:10:52 2026 -0700

    sf-orchestrator: unwedge from May-7 schema-missing freeze
    
    - apply db/schema.sql (palettes/sites/stages/manager_findings/actions_log/analytics_events all missing)
    - seed 20 fashion-house palettes via scripts/seed-palettes.js
    - add global error middleware + express-async-errors so async pg throws no longer leave responses hanging
    - wire BASIC_AUTH into ecosystem.config.js env (was unset → process.exit(1) on every restart → max-restart kill → silent absence)
    - smoke: GET /health 200, GET /sites {sites:[]}, GET /palettes count=20
---
 ecosystem.config.js    |  9 ++++++++-
 orchestrator/server.js | 11 +++++++++++
 package-lock.json      | 10 ++++++++++
 package.json           |  1 +
 4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/ecosystem.config.js b/ecosystem.config.js
index 38a155d..ecdaa60 100644
--- a/ecosystem.config.js
+++ b/ecosystem.config.js
@@ -11,7 +11,14 @@ module.exports = {
       name: 'sf-orchestrator',
       script: 'orchestrator/server.js',
       cwd: __dirname,
-      env: { NODE_ENV: 'production', PORT: 9880 },
+      // BASIC_AUTH required — orchestrator binds 127.0.0.1 only, so this is
+      // defense-in-depth against other local processes (per the P1 fix
+      // 2026-05-04). Override via shell env if you need a different cred.
+      env: {
+        NODE_ENV: 'production',
+        PORT: 9880,
+        BASIC_AUTH: 'admin:DWSecure2024!',
+      },
       max_memory_restart: '512M',
       autorestart: true,
       out_file: 'logs/sf-orchestrator.out.log',
diff --git a/orchestrator/server.js b/orchestrator/server.js
index 62f90b9..44ee5f0 100644
--- a/orchestrator/server.js
+++ b/orchestrator/server.js
@@ -1,5 +1,6 @@
 // site-factory orchestrator — REST + WS for the pipeline & 3D viewer.
 // Stages 0..10. Manager critic runs after every stage (wired in Wave B).
+require('express-async-errors');
 const express = require('express');
 const helmet = require('helmet');
 const cors = require('cors');
@@ -245,6 +246,16 @@ app.post('/sites/:domain/run-stage/:n', async (req, res) => {
   } catch (e) { res.status(500).json({ error: e.message }); }
 });
 
+// Global error middleware — every async route handler above can throw
+// (pg "relation does not exist", connection timeouts, JSON parse, etc).
+// Without this, an unhandled rejection leaves the response hanging until
+// the client times out and the next poll silently fails. Added 2026-05-19
+// after the May-7 schema-missing incident froze cncp-site-factory.json.
+app.use((err, _req, res, _next) => {
+  console.error(`[orchestrator] ${err.code || ''} ${err.message}`);
+  res.status(500).json({ error: err.message, code: err.code || null });
+});
+
 // ─── HTTP + WS ───────────────────────────────────────────────────────────
 const server = http.createServer(app);
 const wss = new WebSocketServer({ server, path: '/ws' });
diff --git a/package-lock.json b/package-lock.json
index 9b62d65..40e4412 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
       "dependencies": {
         "cors": "^2.8.5",
         "express": "^4.19.2",
+        "express-async-errors": "^3.1.1",
         "helmet": "^8.1.0",
         "pg": "^8.11.5",
         "ws": "^8.17.1"
@@ -312,6 +313,15 @@
         "url": "https://opencollective.com/express"
       }
     },
+    "node_modules/express-async-errors": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
+      "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
+      "license": "ISC",
+      "peerDependencies": {
+        "express": "^4.16.2"
+      }
+    },
     "node_modules/finalhandler": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
diff --git a/package.json b/package.json
index 9c47cfc..7d0208c 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
   "dependencies": {
     "cors": "^2.8.5",
     "express": "^4.19.2",
+    "express-async-errors": "^3.1.1",
     "helmet": "^8.1.0",
     "pg": "^8.11.5",
     "ws": "^8.17.1"

← 5af85e2 snapshot — gitify backup 2026-05-19  ·  back to Site Factory  ·  sf-viewer: add missing BASIC_AUTH env (same fix as sf-orches 5a1cbc4 →