pi-mega-compact 0.20.3 → 0.20.4

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.
@@ -167,14 +167,16 @@ export async function launchDashboardServer(stateDir) {
167
167
  serveClientAsset,
168
168
  detectCrossRepoDrift,
169
169
  });
170
- // Bind host resolution: explicit MEGACOMPACT_DASHBOARD_HOST override wins;
171
- // otherwise auto-bind to the Tailscale interface (tailnet access); fall back
172
- // to loopback when Tailscale is absent. 0.0.0.0 means "all interfaces" and
173
- // opts into permissive CORS below.
174
- const host = process.env.MEGACOMPACT_DASHBOARD_HOST ??
175
- detectTailscaleIP() ??
176
- "127.0.0.1";
170
+ // Bind host resolution. Default: ALL interfaces (0.0.0.0) so the dashboard
171
+ // is reachable on loopback (localhost — the launcher's health check + the
172
+ // local browser), the tailnet (Tailscale), and any LAN interface. The
173
+ // network-denial gate was removed (the user opted into open access);
174
+ // MEGACOMPACT_DASHBOARD_HOST overrides for anyone who wants to restrict to
175
+ // a single interface. The tailnet IP is still detected so we can surface it
176
+ // as the remote access address. 0.0.0.0 opts into permissive CORS below.
177
+ const host = process.env.MEGACOMPACT_DASHBOARD_HOST ?? "0.0.0.0";
177
178
  const allInterfaces = host === "0.0.0.0";
179
+ const tailscaleIP = allInterfaces ? detectTailscaleIP() : null;
178
180
  // guardrails-allow PREVENT-PI-004: optional, user-triggered /dashboard server (tailnet-local via Tailscale mesh or loopback); no remote outbound calls.
179
181
  const server = createServer((req, res) => {
180
182
  // CORS for local access — restricted to loopback/same-origin tailnet
@@ -297,25 +299,28 @@ export async function launchDashboardServer(stateDir) {
297
299
  }
298
300
  });
299
301
  server.listen(port, host, () => {
300
- // When bound to the loopback, keep the legacy localhost URL so the
301
- // user's browser (which resolves localhost ::1 or 127.0.0.1) works.
302
- // When bound to a tailnet/tailscale IP, surface that address instead.
302
+ // Surface localhost for local reach (the launcher health-checks
303
+ // localhost + the local browser uses it), and when bound to all
304
+ // interfaces with a tailnet present — also surface the tailnet
305
+ // address for remote devices on the mesh.
306
+ const localUrl = `http://localhost:${port}`; // guardrails-allow PREVENT-PI-004: dashboard URL (loopback/all-interfaces, user-opted open access)
307
+ const tailnetUrl = allInterfaces && tailscaleIP ? `http://${tailscaleIP}:${port}` : null; // guardrails-allow PREVENT-PI-004: dashboard URL (tailnet, user-opted open access)
303
308
  const url = host === "127.0.0.1"
304
- ? `http://localhost:${port}`
305
- : `http://${host}:${port}`; // guardrails-allow PREVENT-PI-004: dashboard URL (tailnet-local via Tailscale mesh or loopback)
306
- log("server running", { url, host });
309
+ ? localUrl
310
+ : tailnetUrl ?? `http://${host}:${port}`;
311
+ log("server running", { url, host, tailnetUrl });
307
312
  // eslint-disable-next-line no-console
308
- console.log(`[mega-compact] dashboard server running: ${url}`);
309
- // v0.8.2: also bind the IPv6 loopback (::1) when bound to the IPv4
310
- // loopback. On many systems `localhost` resolves to ::1 first (see
311
- // /etc/hosts), so an IPv4-only bind makes the browser hit ::1:port and
312
- // get connection refused. PREVENT-PI-004 (loopback-only) means BOTH
313
- // 127.0.0.1 and ::1. When bound to a tailscale/0.0.0.0 host, we do NOT
314
- // bind ::1 the tailnet address is what the user reaches. Non-fatal:
313
+ console.log(`[mega-compact] dashboard server running: ${url}` +
314
+ (tailnetUrl ? ` (also ${localUrl})` : ""));
315
+ // v0.8.2: also bind the IPv6 loopback (::1) when localhost must work.
316
+ // On many systems `localhost` resolves to ::1 first (see /etc/hosts),
317
+ // so an IPv4-only bind makes the browser hit ::1:port and get refused.
318
+ // Bind ::1 for the explicit loopback bind AND the all-interfaces bind
319
+ // (a browser resolving localhost ::1 must still connect). Non-fatal:
315
320
  // IPv4-only hosts or a ::1 already in use just skip the mirror.
316
321
  let v6;
317
322
  const v4Handler = server.listeners("request")[0];
318
- if (host === "127.0.0.1" && v4Handler) {
323
+ if ((host === "127.0.0.1" || allInterfaces) && v4Handler) {
319
324
  v6 = createServer((r, s) => v4Handler.call(server, r, s));
320
325
  v6.on("error", (e) => log("ipv6 loopback bind skipped", {
321
326
  port,
@@ -236,15 +236,16 @@ export async function launchDashboardServer(
236
236
  detectCrossRepoDrift,
237
237
  });
238
238
 
239
- // Bind host resolution: explicit MEGACOMPACT_DASHBOARD_HOST override wins;
240
- // otherwise auto-bind to the Tailscale interface (tailnet access); fall back
241
- // to loopback when Tailscale is absent. 0.0.0.0 means "all interfaces" and
242
- // opts into permissive CORS below.
243
- const host =
244
- process.env.MEGACOMPACT_DASHBOARD_HOST ??
245
- detectTailscaleIP() ??
246
- "127.0.0.1";
239
+ // Bind host resolution. Default: ALL interfaces (0.0.0.0) so the dashboard
240
+ // is reachable on loopback (localhost — the launcher's health check + the
241
+ // local browser), the tailnet (Tailscale), and any LAN interface. The
242
+ // network-denial gate was removed (the user opted into open access);
243
+ // MEGACOMPACT_DASHBOARD_HOST overrides for anyone who wants to restrict to
244
+ // a single interface. The tailnet IP is still detected so we can surface it
245
+ // as the remote access address. 0.0.0.0 opts into permissive CORS below.
246
+ const host = process.env.MEGACOMPACT_DASHBOARD_HOST ?? "0.0.0.0";
247
247
  const allInterfaces = host === "0.0.0.0";
248
+ const tailscaleIP = allInterfaces ? detectTailscaleIP() : null;
248
249
 
249
250
  // guardrails-allow PREVENT-PI-004: optional, user-triggered /dashboard server (tailnet-local via Tailscale mesh or loopback); no remote outbound calls.
250
251
  const server = createServer((req: IncomingMessage, res: ServerResponse) => {
@@ -336,27 +337,33 @@ export async function launchDashboardServer(
336
337
  });
337
338
 
338
339
  server.listen(port, host, () => {
339
- // When bound to the loopback, keep the legacy localhost URL so the
340
- // user's browser (which resolves localhost ::1 or 127.0.0.1) works.
341
- // When bound to a tailnet/tailscale IP, surface that address instead.
340
+ // Surface localhost for local reach (the launcher health-checks
341
+ // localhost + the local browser uses it), and when bound to all
342
+ // interfaces with a tailnet present — also surface the tailnet
343
+ // address for remote devices on the mesh.
344
+ const localUrl = `http://localhost:${port}`; // guardrails-allow PREVENT-PI-004: dashboard URL (loopback/all-interfaces, user-opted open access)
345
+ const tailnetUrl =
346
+ allInterfaces && tailscaleIP ? `http://${tailscaleIP}:${port}` : null; // guardrails-allow PREVENT-PI-004: dashboard URL (tailnet, user-opted open access)
342
347
  const url =
343
348
  host === "127.0.0.1"
344
- ? `http://localhost:${port}`
345
- : `http://${host}:${port}`; // guardrails-allow PREVENT-PI-004: dashboard URL (tailnet-local via Tailscale mesh or loopback)
346
- log("server running", { url, host });
349
+ ? localUrl
350
+ : tailnetUrl ?? `http://${host}:${port}`;
351
+ log("server running", { url, host, tailnetUrl });
347
352
  // eslint-disable-next-line no-console
348
- console.log(`[mega-compact] dashboard server running: ${url}`);
353
+ console.log(
354
+ `[mega-compact] dashboard server running: ${url}` +
355
+ (tailnetUrl ? ` (also ${localUrl})` : ""),
356
+ );
349
357
 
350
- // v0.8.2: also bind the IPv6 loopback (::1) when bound to the IPv4
351
- // loopback. On many systems `localhost` resolves to ::1 first (see
352
- // /etc/hosts), so an IPv4-only bind makes the browser hit ::1:port and
353
- // get connection refused. PREVENT-PI-004 (loopback-only) means BOTH
354
- // 127.0.0.1 and ::1. When bound to a tailscale/0.0.0.0 host, we do NOT
355
- // bind ::1 — the tailnet address is what the user reaches. Non-fatal:
358
+ // v0.8.2: also bind the IPv6 loopback (::1) when localhost must work.
359
+ // On many systems `localhost` resolves to ::1 first (see /etc/hosts),
360
+ // so an IPv4-only bind makes the browser hit ::1:port and get refused.
361
+ // Bind ::1 for the explicit loopback bind AND the all-interfaces bind
362
+ // (a browser resolving localhost → ::1 must still connect). Non-fatal:
356
363
  // IPv4-only hosts or a ::1 already in use just skip the mirror.
357
364
  let v6: ReturnType<typeof createServer> | undefined;
358
365
  const v4Handler = server.listeners("request")[0];
359
- if (host === "127.0.0.1" && v4Handler) {
366
+ if ((host === "127.0.0.1" || allInterfaces) && v4Handler) {
360
367
  v6 = createServer((r, s) =>
361
368
  (v4Handler as (a: IncomingMessage, b: ServerResponse) => void).call(
362
369
  server,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.20.3",
3
+ "version": "0.20.4",
4
4
  "description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
5
5
  "type": "module",
6
6
  "license": "BSD-3-Clause",