@nac3/forge-cli 1.9.1 → 1.9.3
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/dist/chat/server.d.ts.map +1 -1
- package/dist/chat/server.js +46 -31
- package/dist/chat/server.js.map +1 -1
- package/dist/chat/tools/config_write.d.ts +2 -3
- package/dist/chat/tools/config_write.d.ts.map +1 -1
- package/dist/chat/tools/config_write.js +3 -13
- package/dist/chat/tools/config_write.js.map +1 -1
- package/dist/core/forge_profile.d.ts +1 -1
- package/dist/core/forge_profile.d.ts.map +1 -1
- package/dist/core/forge_profile.js +33 -1
- package/dist/core/forge_profile.js.map +1 -1
- package/dist/core/operate_guard.d.ts +3 -0
- package/dist/core/operate_guard.d.ts.map +1 -1
- package/dist/core/operate_guard.js +21 -4
- package/dist/core/operate_guard.js.map +1 -1
- package/dist/core/provider_models.d.ts.map +1 -1
- package/dist/core/provider_models.js +7 -5
- package/dist/core/provider_models.js.map +1 -1
- package/dist/core/public_origin.d.ts +56 -0
- package/dist/core/public_origin.d.ts.map +1 -0
- package/dist/core/public_origin.js +142 -0
- package/dist/core/public_origin.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAKjG,OAAO,EAAoD,KAAK,aAAa,EAAoB,MAAM,aAAa,CAAC;AAErH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAEL,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAczB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAsBjD,OAAO,EAAyD,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"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"}
|
package/dist/chat/server.js
CHANGED
|
@@ -43,6 +43,7 @@ import { readProjectIdentityCached, formatProjectIdentityLines } from '../core/p
|
|
|
43
43
|
import { buildDoctrineDigestLines } from './doctrine_digest.js';
|
|
44
44
|
import { acquireProjectLock, DuplicateInstanceError } from './instance_lock.js';
|
|
45
45
|
import { profilePromptLines, initProfile, activeProfile, operateEnabled, operateConfig } from '../core/forge_profile.js';
|
|
46
|
+
import { checkMutatingRequest, publicOrigins } from '../core/public_origin.js';
|
|
46
47
|
import { isAllowedSlot, listAllowedSlots } from '../core/provider_keys.js';
|
|
47
48
|
import { toolStatusSection, startToolStatusRefresh, environmentLines } from './tool_status.js';
|
|
48
49
|
import { RelayPublisher } from '../relay/relay_publisher.js';
|
|
@@ -141,6 +142,14 @@ export async function startChatServer(opts) {
|
|
|
141
142
|
if (tables.length)
|
|
142
143
|
console.error('[yf] tablas: ' + tables.join(', '));
|
|
143
144
|
}
|
|
145
|
+
/* Servido detras de un reverse proxy: sin esto, todo request mutante
|
|
146
|
+
* del panel se rechaza por Host/Origin no-loopback. Decirlo en el boot
|
|
147
|
+
* es la diferencia entre "no valida la key" y saber por que. */
|
|
148
|
+
const po = publicOrigins();
|
|
149
|
+
if (po.length) {
|
|
150
|
+
console.error('[yf] origen publico autorizado (YF_PUBLIC_ORIGIN): '
|
|
151
|
+
+ po.map((o) => o.origin || o.hostname).join(', '));
|
|
152
|
+
}
|
|
144
153
|
}
|
|
145
154
|
catch { /* noop */ }
|
|
146
155
|
}
|
|
@@ -1379,38 +1388,18 @@ function relayForward(event, data) {
|
|
|
1379
1388
|
* panel's own requests carry Origin http://127.0.0.1:<port>, so
|
|
1380
1389
|
* legitimate traffic passes; non-browser clients (tests, relay)
|
|
1381
1390
|
* send no Origin and are unaffected. No feature is lost. */
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
const c = h.indexOf(':');
|
|
1392
|
-
return c >= 0 ? h.slice(0, c) : h;
|
|
1393
|
-
}
|
|
1391
|
+
/* La lista de loopback y el parseo del Host viven en core/public_origin.ts,
|
|
1392
|
+
* junto con la decision pura que testea `public-origin`. */
|
|
1393
|
+
/* El panel liga 127.0.0.1 y exige Host + Origin loopback en todo request
|
|
1394
|
+
* mutante (DNS-rebinding + CSRF). Eso vale para el modo normal (tunel SSH),
|
|
1395
|
+
* pero el embed residente se publica por un vhost con auth_request, y ahi
|
|
1396
|
+
* nginx reenvia `Host: forge.<host>` y el navegador manda ese Origin: TODO
|
|
1397
|
+
* POST caia con 403 -- validar la API key, mandar un mensaje, aprobar un
|
|
1398
|
+
* modal (visto desplegando ADIP-Kikan, 2026-10-10). El despliegue declara su
|
|
1399
|
+
* origen publico legitimo en YF_PUBLIC_ORIGIN; lo demas sigue rechazado. */
|
|
1394
1400
|
function isLocalMutatingRequestOk(req) {
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1397
|
-
return { ok: false, reason: 'Host no-loopback rechazado (posible DNS-rebinding): ' + host.slice(0, 60) };
|
|
1398
|
-
}
|
|
1399
|
-
const origin = req.headers.origin;
|
|
1400
|
-
if (typeof origin === 'string' && origin && origin.toLowerCase() !== 'null') {
|
|
1401
|
-
let oh;
|
|
1402
|
-
try {
|
|
1403
|
-
oh = new URL(origin).hostname.toLowerCase();
|
|
1404
|
-
}
|
|
1405
|
-
catch {
|
|
1406
|
-
return { ok: false, reason: 'Origin malformado' };
|
|
1407
|
-
}
|
|
1408
|
-
const normalized = oh.startsWith('[') ? oh : oh; /* URL.hostname already strips ipv6 brackets to bare ::1 on Node */
|
|
1409
|
-
if (!LOOPBACK_HOSTS.has(normalized) && !LOOPBACK_HOSTS.has('[' + normalized + ']')) {
|
|
1410
|
-
return { ok: false, reason: 'Origin cross-site rechazado (CSRF): ' + origin.slice(0, 80) };
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
return { ok: true };
|
|
1401
|
+
const r = checkMutatingRequest(String(req.headers.host ?? ''), req.headers.origin, publicOrigins());
|
|
1402
|
+
return r.ok ? { ok: true } : { ok: false, reason: r.reason || 'rechazado' };
|
|
1414
1403
|
}
|
|
1415
1404
|
const MUTATING_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
|
|
1416
1405
|
async function route(req, res, ctx) {
|
|
@@ -3044,6 +3033,10 @@ async function handleNac3Approve(req, res, ctx) {
|
|
|
3044
3033
|
});
|
|
3045
3034
|
return;
|
|
3046
3035
|
}
|
|
3036
|
+
const failed = result.is_error === true;
|
|
3037
|
+
const errText = failed
|
|
3038
|
+
? String(result.result?.error ?? 'el handler devolvio error').slice(0, 400)
|
|
3039
|
+
: '';
|
|
3047
3040
|
await logApproval({
|
|
3048
3041
|
ts: new Date().toISOString(),
|
|
3049
3042
|
trace_id: traceId,
|
|
@@ -3051,7 +3044,29 @@ async function handleNac3Approve(req, res, ctx) {
|
|
|
3051
3044
|
decision: 'approve',
|
|
3052
3045
|
args_sample: pending.args,
|
|
3053
3046
|
policy: pending.verb.policy,
|
|
3047
|
+
...(failed ? { reason: 'aprobado pero el handler lo rechazo: ' + errText } : {}),
|
|
3054
3048
|
});
|
|
3049
|
+
/* CIERRE DEL RASTRO (Pablo 2026-10-10, validando operate mode en ADIP-Kikan):
|
|
3050
|
+
* el dispatch log dejaba el verbo en 'awaiting_user_approval' para siempre y
|
|
3051
|
+
* el log de aprobaciones decia 'approve' sin decir QUE paso. Con
|
|
3052
|
+
* require_approval=true -- el default de operate mode -- eso dejaba sin
|
|
3053
|
+
* rastro el resultado de TODOS los cambios de configuracion. */
|
|
3054
|
+
try {
|
|
3055
|
+
const { logDispatch, redactArgs } = await import('../nac3/dispatch_log.js');
|
|
3056
|
+
await logDispatch({
|
|
3057
|
+
ts: new Date().toISOString(),
|
|
3058
|
+
kind: 'invoke',
|
|
3059
|
+
trace_id: traceId,
|
|
3060
|
+
verb_id: pending.verb.id,
|
|
3061
|
+
alias_used: pending.legacy_alias,
|
|
3062
|
+
args_sample: redactArgs(pending.args),
|
|
3063
|
+
policy: pending.verb.policy,
|
|
3064
|
+
side_effects_declared: pending.verb.side_effects,
|
|
3065
|
+
result_ok: !failed,
|
|
3066
|
+
...(failed ? { result_error: errText } : {}),
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
3069
|
+
catch { /* el rastro no puede tumbar la ejecucion ya hecha */ }
|
|
3055
3070
|
sendJson(res, 200, {
|
|
3056
3071
|
ok: true,
|
|
3057
3072
|
trace_id: traceId,
|