@nac3/forge-cli 1.9.0 → 1.9.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"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"}
@@ -42,7 +42,8 @@ import { VERSION } from '../version.js';
42
42
  import { readProjectIdentityCached, formatProjectIdentityLines } from '../core/project_identity.js';
43
43
  import { buildDoctrineDigestLines } from './doctrine_digest.js';
44
44
  import { acquireProjectLock, DuplicateInstanceError } from './instance_lock.js';
45
- import { profilePromptLines, initProfile, activeProfile, operateEnabled } from '../core/forge_profile.js';
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';
@@ -115,6 +116,40 @@ export async function startChatServer(opts) {
115
116
  try {
116
117
  console.error('[yf] perfil de despliegue activo: "' + (prof.name || 'default') + '"'
117
118
  + (prof.read_only ? ' (READ-ONLY diagnostico)' : ''));
119
+ /* Operate mode (Pablo 2026-10-10): el boot log es la UNICA visibilidad
120
+ * que tiene el operador sobre lo que este despliegue puede cambiar, asi
121
+ * que enumera el alcance REAL (no solo que esta encendido) -- y con
122
+ * allowlists vacios lo dice, porque entonces no puede cambiar nada. */
123
+ const op = operateConfig();
124
+ if (op) {
125
+ const files = (op.config_files?.allow || []).filter((g) => typeof g === 'string' && g.trim());
126
+ const tables = (op.config_tables?.allow || []).filter((t) => typeof t === 'string' && t.trim());
127
+ const orch = op.orchestrator?.kind || '';
128
+ const parts = [
129
+ files.length ? files.length + ' glob(s) de archivos' : 'sin archivos',
130
+ tables.length ? tables.length + ' tabla(s)' : 'sin tablas',
131
+ orch ? 'orquestador ' + orch : 'sin orquestador',
132
+ ];
133
+ console.error('[yf] OPERATE MODE ON -- alcance: ' + parts.join(', ')
134
+ + '; aprobacion ' + (op.require_approval === false ? 'DESACTIVADA' : 'por modal')
135
+ + '; journal en ' + (op.journal_dir || '.forge/changes'));
136
+ if (!files.length && !tables.length && !orch) {
137
+ console.error('[yf] OPERATE MODE sin alcance declarado: el asistente NO puede cambiar nada '
138
+ + 'todavia (declara operate.config_files.allow / config_tables.allow / orchestrator).');
139
+ }
140
+ if (files.length)
141
+ console.error('[yf] archivos: ' + files.join(', '));
142
+ if (tables.length)
143
+ console.error('[yf] tablas: ' + tables.join(', '));
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
+ }
118
153
  }
119
154
  catch { /* noop */ }
120
155
  }
@@ -1353,38 +1388,18 @@ function relayForward(event, data) {
1353
1388
  * panel's own requests carry Origin http://127.0.0.1:<port>, so
1354
1389
  * legitimate traffic passes; non-browser clients (tests, relay)
1355
1390
  * send no Origin and are unaffected. No feature is lost. */
1356
- const LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '::1', '[::1]']);
1357
- function hostnameOf(hostHeader) {
1358
- const h = hostHeader.trim().toLowerCase();
1359
- if (!h)
1360
- return '';
1361
- if (h.startsWith('[')) {
1362
- const i = h.indexOf(']');
1363
- return i >= 0 ? h.slice(0, i + 1) : h;
1364
- }
1365
- const c = h.indexOf(':');
1366
- return c >= 0 ? h.slice(0, c) : h;
1367
- }
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. */
1368
1400
  function isLocalMutatingRequestOk(req) {
1369
- const host = hostnameOf(String(req.headers.host ?? ''));
1370
- if (host && !LOOPBACK_HOSTS.has(host)) {
1371
- return { ok: false, reason: 'Host no-loopback rechazado (posible DNS-rebinding): ' + host.slice(0, 60) };
1372
- }
1373
- const origin = req.headers.origin;
1374
- if (typeof origin === 'string' && origin && origin.toLowerCase() !== 'null') {
1375
- let oh;
1376
- try {
1377
- oh = new URL(origin).hostname.toLowerCase();
1378
- }
1379
- catch {
1380
- return { ok: false, reason: 'Origin malformado' };
1381
- }
1382
- const normalized = oh.startsWith('[') ? oh : oh; /* URL.hostname already strips ipv6 brackets to bare ::1 on Node */
1383
- if (!LOOPBACK_HOSTS.has(normalized) && !LOOPBACK_HOSTS.has('[' + normalized + ']')) {
1384
- return { ok: false, reason: 'Origin cross-site rechazado (CSRF): ' + origin.slice(0, 80) };
1385
- }
1386
- }
1387
- 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' };
1388
1403
  }
1389
1404
  const MUTATING_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
1390
1405
  async function route(req, res, ctx) {