← back to Ai Workforce

server.js

55 lines

'use strict';
// ai-workforce — local prototype server. Basic-auth gated. PORT=0 → free port.
// Endpoints: GET /api/snapshot (live fleet), static files from public/.
const http = require('http');
const fs = require('fs');
const path = require('path');
const { snapshot } = require('./lib/collect');

const PORT = parseInt(process.env.PORT || '0', 10);
const USER = process.env.BASIC_AUTH_USER || 'admin';
const PASS = process.env.BASIC_AUTH_PASS || 'DW2024!';
const MIME = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.svg': 'image/svg+xml', '.ico': 'image/x-icon' };

function authed(req) {
  const h = req.headers.authorization || '';
  if (!h.startsWith('Basic ')) return false;
  const [u, p] = Buffer.from(h.slice(6), 'base64').toString().split(':');
  return u === USER && p === PASS;
}

const server = http.createServer(async (req, res) => {
  if (!authed(req)) {
    res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="ai-workforce"' });
    return res.end('auth required');
  }
  const url = req.url.split('?')[0];

  if (url === '/favicon.ico') { res.writeHead(204); return res.end(); }

  if (url === '/api/snapshot') {
    try {
      const snap = await snapshot();
      res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
      return res.end(JSON.stringify(snap));
    } catch (e) {
      res.writeHead(500, { 'Content-Type': 'application/json' });
      return res.end(JSON.stringify({ error: String(e && e.message || e) }));
    }
  }

  // static
  const rel = url === '/' ? 'index.html' : url.replace(/^\/+/, '');
  const fp = path.join(__dirname, 'public', path.normalize(rel).replace(/^(\.\.[\\/])+/, ''));
  if (fp.startsWith(path.join(__dirname, 'public')) && fs.existsSync(fp) && fs.statSync(fp).isFile()) {
    res.writeHead(200, { 'Content-Type': MIME[path.extname(fp)] || 'application/octet-stream' });
    return res.end(fs.readFileSync(fp));
  }
  res.writeHead(404); res.end('not found');
});

server.listen(PORT, function () {
  const p = this.address().port;
  console.log('[ai-workforce] http://localhost:' + p + '  (basic auth ' + USER + ' / ' + PASS + ')');
});