[object Object]

← back to Dw Photo Capture

server.js: bounded /js/ static route to serve the shared capture-pipeline module (TK-12090)

94c8d604f58b6cfbb393e4da34b124d174dbfd66 · 2026-09-23 16:14:39 -0700 · Steve Abrams

Raw-http server has no generic static handler; the extracted public/js/capture-pipeline.js
needs an explicit route. Mirrors the /marketing/ guard: basename-only, .js/.mjs allowlist,
path-traversal guard, no-store. Behind the existing basic-auth (authed page fetches it as a
same-origin subresource).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY

Files touched

Diff

commit 94c8d604f58b6cfbb393e4da34b124d174dbfd66
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 23 16:14:39 2026 -0700

    server.js: bounded /js/ static route to serve the shared capture-pipeline module (TK-12090)
    
    Raw-http server has no generic static handler; the extracted public/js/capture-pipeline.js
    needs an explicit route. Mirrors the /marketing/ guard: basename-only, .js/.mjs allowlist,
    path-traversal guard, no-store. Behind the existing basic-auth (authed page fetches it as a
    same-origin subresource).
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
---
 server.js | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/server.js b/server.js
index 71cbc16..66e3f30 100644
--- a/server.js
+++ b/server.js
@@ -2110,6 +2110,25 @@ load();
     return send(res, 404, { err: 'not found' });
   }
 
+  // ── Shared front-end modules (public/js/*.js) — bounded static serve for the extracted
+  //    capture-pipeline engine (and any future shared module). Same posture as /marketing/:
+  //    basename-only + .js/.mjs allowlist + path-traversal guard. Behind the app basic-auth
+  //    (the authed page fetches it as a same-origin subresource, so creds ride along).
+  //    no-store so a redeploy of the module takes effect immediately (mirrors the HTML pages).
+  if (_p.startsWith('/js/')) {
+    const name = _p.slice('/js/'.length);
+    if (name.includes('/') || name.includes('..') || !/^[A-Za-z0-9._-]+\.m?js$/.test(name)) {
+      return send(res, 404, { err: 'not found' });
+    }
+    const JDIR = path.join(ROOT, 'public/js');
+    const fp = path.join(JDIR, name);
+    if (!fp.startsWith(JDIR + path.sep) || !fs.existsSync(fp) || !fs.statSync(fp).isFile()) {
+      return send(res, 404, { err: 'not found' });
+    }
+    res.writeHead(200, { 'Content-Type': 'application/javascript; charset=utf-8', 'Cache-Control': 'no-store' });
+    return res.end(fs.readFileSync(fp));
+  }
+
   // App icons + PWA manifest — make "Add to Home Screen" a real app (clean DW icon, fullscreen).
   if (u.pathname === '/icon-180.png' || u.pathname === '/icon-192.png' || u.pathname === '/icon-512.png' || u.pathname === '/apple-touch-icon.png') {
     const f = path.join(ROOT, 'public', u.pathname === '/apple-touch-icon.png' ? 'icon-180.png' : path.basename(u.pathname));

← 63b4de0 auto-data-snapshot: 2026-09-23T15:21:10 (2 data files) — vis  ·  back to Dw Photo Capture  ·  add shared capture-pipeline.js engine (full pre-capture phot fdff137 →