nothumanallowed 13.5.138 → 13.5.139

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.139",
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": {
@@ -5304,6 +5304,59 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
5304
5304
  patchJsFiles(path.join(sandboxDir, 'server'), path.join(sandboxDir, 'server'));
5305
5305
  sendLog('🔧 Shim iniettati: DB (in-memory), Sentinel WAF, Cache — require() patchati');
5306
5306
 
5307
+ // Post-process server/index.js: fix static path + ensure SPA fallback
5308
+ // The LLM sometimes generates a relative path ('public') instead of the absolute
5309
+ // path.join(__dirname, '..', 'public') — causing "Not found: /" when the cwd
5310
+ // differs from the project root.
5311
+ const serverIndexPath = path.join(sandboxDir, 'server', 'index.js');
5312
+ if (fs.existsSync(serverIndexPath)) {
5313
+ let srvSrc = fs.readFileSync(serverIndexPath, 'utf8');
5314
+ let srvChanged = false;
5315
+
5316
+ // Fix: express.static('public') / express.static("public") → absolute path
5317
+ const staticRelRe = /express\.static\s*\(\s*['"]\.?\/?public['"]\s*\)/g;
5318
+ const staticAbsolute = "express.static(path.join(__dirname, '..', 'public'))";
5319
+ if (staticRelRe.test(srvSrc)) {
5320
+ srvSrc = srvSrc.replace(staticRelRe, staticAbsolute);
5321
+ srvChanged = true;
5322
+ }
5323
+
5324
+ // Fix: express.static(path.join(__dirname, 'public')) → go up one level
5325
+ const staticWrongDepth = /express\.static\s*\(\s*path\.join\s*\(\s*__dirname\s*,\s*['"]public['"]\s*\)\s*\)/g;
5326
+ if (staticWrongDepth.test(srvSrc)) {
5327
+ srvSrc = srvSrc.replace(staticWrongDepth, staticAbsolute);
5328
+ srvChanged = true;
5329
+ }
5330
+
5331
+ // Ensure 'path' is required if we injected path.join
5332
+ if (srvChanged && !/require\(['"]path['"]\)/.test(srvSrc)) {
5333
+ srvSrc = "const path = require('path');\n" + srvSrc;
5334
+ }
5335
+
5336
+ // Inject SPA fallback before the 404 / error handler if missing
5337
+ // Detects: app.use((req,res,next)... or app.use(function(err... or app.use(errorHandler)
5338
+ // and inserts the wildcard GET before it
5339
+ const hasSpaFallback = /app\s*\.\s*get\s*\(\s*['"]\*['"]/.test(srvSrc);
5340
+ if (!hasSpaFallback) {
5341
+ 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";
5342
+ // Insert before the 404 handler (app.use with 4-arg function) or before app.listen
5343
+ const listenIdx = srvSrc.lastIndexOf('app.listen');
5344
+ const notFoundIdx = srvSrc.search(/app\.use\s*\(\s*(notFoundHandler|\(req,\s*res\)|function\s*\(req,\s*res)/);
5345
+ const insertAt = notFoundIdx !== -1 ? notFoundIdx : listenIdx;
5346
+ if (insertAt !== -1) {
5347
+ srvSrc = srvSrc.slice(0, insertAt) + spaFallback + srvSrc.slice(insertAt);
5348
+ } else {
5349
+ srvSrc += spaFallback;
5350
+ }
5351
+ srvChanged = true;
5352
+ }
5353
+
5354
+ if (srvChanged) {
5355
+ fs.writeFileSync(serverIndexPath, srvSrc, 'utf8');
5356
+ sendLog('🔧 server/index.js: static path corretto + SPA fallback iniettato');
5357
+ }
5358
+ }
5359
+
5307
5360
  // Patch package.json to remove pg, add only what's needed
5308
5361
  const pkgPath = path.join(sandboxDir, 'package.json');
5309
5362
  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.139';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -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).' },