nothumanallowed 13.5.138 → 13.5.140

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "13.5.138",
3
+ "version": "13.5.140",
4
4
  "description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -5145,6 +5145,7 @@ module.exports.notFoundHandler = notFoundHandler;
5145
5145
  // Always overwrite — older shim versions may be missing exports like notFoundHandler
5146
5146
  fs.writeFileSync(path.join(sandboxDir, 'server', 'middleware', 'errors.js'), errorsShim, 'utf8');
5147
5147
 
5148
+
5148
5149
  // Models shim — LLM often generates require('../models/User') etc. that don't exist
5149
5150
  // Create a generic User model shim backed by the in-memory DB shim
5150
5151
  const userModelShim = `
@@ -5304,6 +5305,59 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
5304
5305
  patchJsFiles(path.join(sandboxDir, 'server'), path.join(sandboxDir, 'server'));
5305
5306
  sendLog('🔧 Shim iniettati: DB (in-memory), Sentinel WAF, Cache — require() patchati');
5306
5307
 
5308
+ // Post-process server/index.js: fix static path + ensure SPA fallback
5309
+ // The LLM sometimes generates a relative path ('public') instead of the absolute
5310
+ // path.join(__dirname, '..', 'public') — causing "Not found: /" when the cwd
5311
+ // differs from the project root.
5312
+ const serverIndexPath = path.join(sandboxDir, 'server', 'index.js');
5313
+ if (fs.existsSync(serverIndexPath)) {
5314
+ let srvSrc = fs.readFileSync(serverIndexPath, 'utf8');
5315
+ let srvChanged = false;
5316
+
5317
+ // Fix: express.static('public') / express.static("public") → absolute path
5318
+ const staticRelRe = /express\.static\s*\(\s*['"]\.?\/?public['"]\s*\)/g;
5319
+ const staticAbsolute = "express.static(path.join(__dirname, '..', 'public'))";
5320
+ if (staticRelRe.test(srvSrc)) {
5321
+ srvSrc = srvSrc.replace(staticRelRe, staticAbsolute);
5322
+ srvChanged = true;
5323
+ }
5324
+
5325
+ // Fix: express.static(path.join(__dirname, 'public')) → go up one level
5326
+ const staticWrongDepth = /express\.static\s*\(\s*path\.join\s*\(\s*__dirname\s*,\s*['"]public['"]\s*\)\s*\)/g;
5327
+ if (staticWrongDepth.test(srvSrc)) {
5328
+ srvSrc = srvSrc.replace(staticWrongDepth, staticAbsolute);
5329
+ srvChanged = true;
5330
+ }
5331
+
5332
+ // Ensure 'path' is required if we injected path.join
5333
+ if (srvChanged && !/require\(['"]path['"]\)/.test(srvSrc)) {
5334
+ srvSrc = "const path = require('path');\n" + srvSrc;
5335
+ }
5336
+
5337
+ // Inject SPA fallback before the 404 / error handler if missing
5338
+ // Detects: app.use((req,res,next)... or app.use(function(err... or app.use(errorHandler)
5339
+ // and inserts the wildcard GET before it
5340
+ const hasSpaFallback = /app\s*\.\s*get\s*\(\s*['"]\*['"]/.test(srvSrc);
5341
+ if (!hasSpaFallback) {
5342
+ const spaFallback = "\n// SPA fallback — serve index.html for all unmatched GET routes\napp.get('*', (req, res) => res.sendFile(path.join(__dirname, '..', 'public', 'index.html')));\n";
5343
+ // Insert before the 404 handler (app.use with 4-arg function) or before app.listen
5344
+ const listenIdx = srvSrc.lastIndexOf('app.listen');
5345
+ const notFoundIdx = srvSrc.search(/app\.use\s*\(\s*(notFoundHandler|\(req,\s*res\)|function\s*\(req,\s*res)/);
5346
+ const insertAt = notFoundIdx !== -1 ? notFoundIdx : listenIdx;
5347
+ if (insertAt !== -1) {
5348
+ srvSrc = srvSrc.slice(0, insertAt) + spaFallback + srvSrc.slice(insertAt);
5349
+ } else {
5350
+ srvSrc += spaFallback;
5351
+ }
5352
+ srvChanged = true;
5353
+ }
5354
+
5355
+ if (srvChanged) {
5356
+ fs.writeFileSync(serverIndexPath, srvSrc, 'utf8');
5357
+ sendLog('🔧 server/index.js: static path corretto + SPA fallback iniettato');
5358
+ }
5359
+ }
5360
+
5307
5361
  // Patch package.json to remove pg, add only what's needed
5308
5362
  const pkgPath = path.join(sandboxDir, 'package.json');
5309
5363
  let pkg = {};
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '13.5.138';
8
+ export const VERSION = '13.5.140';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -8545,7 +8545,7 @@ function wcDiffPanelHtml() {
8545
8545
  var items = _wcDiffQueue.map(function(d, di) {
8546
8546
  var addedLines = (d.after||'').split(String.fromCharCode(10)).length - (d.before||'').split(String.fromCharCode(10)).length;
8547
8547
  var sign = addedLines >= 0 ? '+' : '';
8548
- return '<details style="border:1px solid var(--border);border-radius:6px;margin-bottom:6px;background:var(--bg3)">' +
8548
+ return '<details open style="border:1px solid var(--border);border-radius:6px;margin-bottom:6px;background:var(--bg3)">' +
8549
8549
  '<summary style="padding:7px 10px;cursor:pointer;font-size:11px;font-family:var(--mono);color:var(--text);list-style:none;display:flex;align-items:center;gap:8px">' +
8550
8550
  '<span style="color:var(--green);font-size:10px">&#9650;</span>' +
8551
8551
  '<span style="flex:1">' + wcEsc(d.file) + '</span>' +
@@ -8764,7 +8764,7 @@ async function wcGenerate() {
8764
8764
  { name: 'server/services/email.js', lang: 'javascript', prompt: 'Generate server/services/email.js: Nodemailer transporter using SMTP from env. Function sendVerificationEmail(to, token, baseUrl): sends HTML email with verification link. Function sendPasswordResetEmail(to, token, baseUrl). Add SendGrid fallback (commented out, predisposed with transporter swap). Never expose credentials.' },
8765
8765
  { name: 'server/routes/auth.js', lang: 'javascript', prompt: 'Generate server/routes/auth.js: POST /register (validate fields: '+authFieldsDef+', check duplicate email, bcrypt hash password cost 12, insert user, send verification email, return 201), POST /login (validate, check email verified, compare bcrypt, issue JWT access 15min + refresh 7d httpOnly cookie), POST /logout (clear refresh cookie), POST /refresh-token (validate refresh from httpOnly cookie, rotate token), GET /verify-email/:token (mark email verified). Use parameterized queries only. Import authLimiter EXACTLY like this: const { authLimiter } = require("../middleware/security"); — do NOT create or import from ../middleware/rateLimiter (that file does not exist). Apply authLimiter to register and login.' },
8766
8766
  { name: 'server/routes/api.js', lang: 'javascript', prompt: 'Generate server/routes/api.js: Express router with a verifyToken middleware (validates JWT Bearer). GET /api/me returns authenticated user profile (no password hash). GET /api/health returns {status: ok, timestamp}. Structure ready for adding more routes.' },
8767
- { name: 'server/index.js', lang: 'javascript', prompt: 'Generate server/index.js: Express app entry point. Apply applySecurityMiddleware first. Then apply sentinelMiddleware (import from ./middleware/sentinel.js). Use CORS with env CORS_ORIGIN. Parse JSON body (limit 10kb). Mount /api/auth auth.js, /api api.js. Serve public/ as static. 404 handler and global error handler (never leak stack traces in production). Start on PORT from env.' },
8767
+ { name: 'server/index.js', lang: 'javascript', prompt: 'Generate server/index.js: Express app entry point. Apply applySecurityMiddleware first. Then apply sentinelMiddleware (import from ./middleware/sentinel.js). Use CORS with env CORS_ORIGIN. Parse JSON body (limit 10kb). Mount /api/auth to auth.js, /api to api.js. CRITICAL: serve static files using the ABSOLUTE path computed with path.join and __dirname — specifically path.join(__dirname, double-dot, public) so it resolves correctly regardless of cwd. After mounting all API routes and before the 404 handler, add a SPA catch-all: app.get with wildcard star that calls res.sendFile with path.join(__dirname, double-dot, public, index.html). This ensures GET / and any unmatched frontend route returns index.html instead of a 404 JSON error. 404 handler and global error handler (never leak stack traces in production). Start on PORT from env.' },
8768
8768
  { name: 'db/migrations/001_init.sql', lang: 'sql', prompt: 'Generate PostgreSQL migration 001_init.sql: CREATE TABLE users with id UUID default gen_random_uuid(), fields for '+authFieldsDef+', email_verified BOOLEAN default false, verification_token VARCHAR, reset_token VARCHAR, reset_token_expires TIMESTAMPTZ, refresh_token_hash VARCHAR, created_at TIMESTAMPTZ default now(), updated_at TIMESTAMPTZ default now(). CREATE INDEX on email. CREATE TABLE refresh_tokens (id, user_id FK, token_hash, expires_at, created_at). Add updated_at trigger function.' },
8769
8769
  { name: 'public/css/base.css', lang: 'css', prompt: 'Generate public/css/base.css: CSS custom properties (color palette, spacing scale, font scale, border-radius, shadows, transitions). CSS reset (*, box-sizing). Base typography (Inter or system-ui). Utility classes using BEM where applicable. Dark/light mode via prefers-color-scheme.' },
8770
8770
  { name: 'public/css/components.css', lang: 'css', prompt: 'Generate public/css/components.css following STRICT BEM (block__element--modifier). Components: .btn (--primary, --secondary, --danger, --ghost), .form (form__field, form__label, form__input, form__error, form__hint), .card (card__header, card__body, card__footer), .nav (nav__brand, nav__links, nav__link--active), .alert (--success, --error, --warning, --info), .spinner, .badge, .modal (modal__overlay, modal__content, modal__header, modal__body, modal__footer). Fully accessible (focus states, aria).' },