← 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 →