Mejoras de sesion: estabilizacion, IA, Nexus Yonke y marketplace B2B
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled

- F0 blindaje: Redis/Celery, pg_hba sin trust LAN, secretos a env 600, backups, webhook auth, jobs muertos
- F1 caja: bugs POS, reembolsos al corte, apartados, CFDI, topes de descuento en cotizacion/apartado
- F2/F7 IA de catalogo: autocategorizacion, dedup de SKUs con embeddings, OCR de facturas, descripciones, claves SAT, limpieza de fitment
- F3 IA en el flujo: vision Yonke, preguntas MeLi, venta cruzada, anomalias, sinonimos, busqueda semantica (rerank/embeddings)
- F4/F8 escala y cartera: /metrics+Prometheus+Grafana, pool, score de credito, churn, metricas multi-tenant
- Nexus Yonke (M1-M6): modelo de datos 1-de-1, alta por donador, vitrina publica, MeLi usado, consignacion, garantia por dias, reportes, etiquetas
- Marketplace B2B entre yonkes (catalogo + pedidos cross-tenant)
- Seguridad: auth en /api/admin/* (35 endpoints), alertas por tenant
- Migraciones v4.27/v4.28; timers expire-demos y rollup-metrics
This commit is contained in:
2026-10-12 00:57:31 +00:00
parent f2d4558b80
commit a386ca5b4a
165 changed files with 31313 additions and 2203 deletions

32
audit_fleet.js Normal file
View File

@@ -0,0 +1,32 @@
const { chromium } = require('playwright');
const { execSync } = require('child_process');
const JWT_SECRET = execSync("grep -oP 'POS_JWT_SECRET=\\K.*' /etc/systemd/system/nexus-pos.service | head -1").toString().trim();
function tok() {
const h = { alg: 'HS256', typ: 'JWT' };
const now = Math.floor(Date.now()/1000);
const p = { tenant_id: 32, employee_id: 1, name: 'Audit', role: 'owner', branch_id: 1,
max_discount_pct: 100, permissions: ['*'], device_id: 'a', type: 'pos_access', exp: now+900, iat: now };
const b64 = o => Buffer.from(JSON.stringify(o)).toString('base64url');
const crypto = require('crypto');
return b64(h)+'.'+b64(p)+'.'+crypto.createHmac('sha256', JWT_SECRET).update(b64(h)+'.'+b64(p)).digest('base64url');
}
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
const errs = [];
page.on('pageerror', e => errs.push(String(e).slice(0,120)));
page.on('console', m => { if (m.type()==='error' && !/favicon|404|net::ERR|sourcemap/i.test(m.text())) errs.push(m.text().slice(0,120)); });
await page.addInitScript(t => {
localStorage.setItem('pos_token', t);
localStorage.setItem('pos_employee', JSON.stringify({id:1,name:'Audit',role:'owner'}));
localStorage.setItem('pos_tenant_id','32');
document.cookie='pos_role=owner; path=/pos; SameSite=Lax';
}, tok());
for (const p of ['/pos/fleet','/pos/supplier-catalog','/pos/historical-sales','/pos/diagrams']) {
errs.length = 0;
const resp = await page.goto('http://localhost:5001'+p, {waitUntil:'load', timeout:20000}).catch(e=>null);
await page.waitForTimeout(2000);
console.log((errs.length?'✗ ':'✓ ') + p + ' [' + (resp?resp.status():'?') + ']' + (errs.length? ' → '+errs[0]:''));
}
await browser.close();
})();