[object Object]

← back to Approval Command Center

ACC: serve public/ static assets so /nav-agent/* resolves (was 404)

c39f11f529241031669d676c52bf6b355f437981 · 2026-08-13 11:56:31 -0700 · Steve Abrams

Raw Node http server only served index.html at /; the injected nav-agent
<link>/<script> 404'd. Added a path-traversal-guarded GET static handler for
public/ before the 404 fallback (mirrors the approvals-viewer 528c44e fix).
Additive + reversible; asset stays behind Basic auth (verified 200 js/css on a
scratch port, 404 on traversal, 401 unauth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit c39f11f529241031669d676c52bf6b355f437981
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Aug 13 11:56:31 2026 -0700

    ACC: serve public/ static assets so /nav-agent/* resolves (was 404)
    
    Raw Node http server only served index.html at /; the injected nav-agent
    <link>/<script> 404'd. Added a path-traversal-guarded GET static handler for
    public/ before the 404 fallback (mirrors the approvals-viewer 528c44e fix).
    Additive + reversible; asset stays behind Basic auth (verified 200 js/css on a
    scratch port, 404 on traversal, 401 unauth).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 server.js | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/server.js b/server.js
index ef8d73b..2f8bbf3 100644
--- a/server.js
+++ b/server.js
@@ -208,6 +208,17 @@ const server = http.createServer(async (req, res) => {
       res.writeHead(200, { 'Content-Type': 'application/json' });
       return res.end(JSON.stringify({ ok: true, recs }));
     }
+    // static assets under public/ (e.g. /nav-agent/nav-agent.js|css) — additive, path-traversal-guarded
+    if (req.method === 'GET') {
+      const MIME = { '.js': 'text/javascript', '.css': 'text/css', '.html': 'text/html', '.json': 'application/json', '.png': 'image/png', '.jpg': 'image/jpeg', '.svg': 'image/svg+xml', '.ico': 'image/x-icon', '.woff2': 'font/woff2' };
+      const pub = path.join(__dirname, 'public');
+      const urlPath = decodeURIComponent(req.url.split('?')[0]);
+      const fp = path.normalize(path.join(pub, urlPath));
+      if (fp.startsWith(pub + path.sep) && fs.existsSync(fp) && fs.statSync(fp).isFile()) {
+        res.writeHead(200, { 'Content-Type': MIME[path.extname(fp).toLowerCase()] || 'application/octet-stream' });
+        return res.end(fs.readFileSync(fp));
+      }
+    }
     res.writeHead(404); res.end('not found');
   } catch (e) {
     res.writeHead(500, { 'Content-Type': 'application/json' });

← a809adc nav-agent: universal grid-controls drop-in on internal dashb  ·  back to Approval Command Center  ·  ACC: RETIRE as superseded duplicate of live approvals-viewer 7c6158f →