openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
102 lines (101 loc) • 6.87 kB
JavaScript
import { n as isVitestRuntimeEnv } from "./test-runtime-env-DQDRzsLt.js";
import "./env-M3R40TOb.js";
import { b as isUnsafeGatewayTailscaleNoAuth, y as formatUnsafeGatewayTailscaleNoAuthMessage } from "./io.types-BUCjdS5v.js";
import { f as isValidIPv4, g as resolveGatewayBindHost, s as isLoopbackHost, t as defaultGatewayBindMode } from "./net-DbNPs6Xm.js";
import { n as resolveGatewayAuth } from "./auth-resolve-O5AKX-sb.js";
import { t as assertGatewayAuthConfigured } from "./auth-CyN_wFeb.js";
import { t as normalizeControlUiBasePath } from "./control-ui-shared-BiO6QP54.js";
import { r as mergeGatewayTailscaleConfig } from "./startup-auth-D92BVWdq.js";
import { t as commitHooksConfigReload, y as resolveHooksConfig } from "./hooks-CdPzVOnm.js";
//#region src/gateway/env-deprecation.ts
const LEGACY_ENV_PREFIXES = ["CLAWDBOT_", "MOLTBOT_"];
let warned = false;
/** Emits a one-time warning when ignored legacy CLAWDBOT_/MOLTBOT_ env vars are present. */
function warnLegacyOpenClawEnvVars(env = process.env) {
if (warned || isVitestRuntimeEnv(env)) return;
const prefixCounts = /* @__PURE__ */ new Map();
for (const key of Object.keys(env)) {
const prefix = LEGACY_ENV_PREFIXES.find((candidate) => key.startsWith(candidate));
if (prefix) prefixCounts.set(prefix, (prefixCounts.get(prefix) ?? 0) + 1);
}
const legacyVarCount = [...prefixCounts.values()].reduce((total, count) => total + count, 0);
if (legacyVarCount === 0) return;
const detectedPrefixes = LEGACY_ENV_PREFIXES.filter((prefix) => prefixCounts.has(prefix)).map((prefix) => `${prefix}*`).join(", ");
process.emitWarning([`Legacy ${detectedPrefixes} environment variables were detected (${legacyVarCount} total), but OpenClaw only reads OPENCLAW_* names now.`, "Rename them by replacing the legacy prefix with OPENCLAW_; the old names are ignored."].join("\n"), {
code: "OPENCLAW_LEGACY_ENV_VARS",
type: "DeprecationWarning"
});
warned = true;
}
//#endregion
//#region src/gateway/server-runtime-config.ts
/** Startup and reload validate the same security policy against the serving listener. */
function assertGatewayRuntimeSecurityConfig(params) {
const { cfg, bindHost, controlUiEnabled, resolvedAuth, tailscaleMode } = params;
const authMode = resolvedAuth.mode;
const hasSharedSecret = authMode === "token" && Boolean(resolvedAuth.token?.trim()) || authMode === "password" && Boolean(resolvedAuth.password?.trim());
const controlUiAllowedOrigins = (cfg.gateway?.controlUi?.allowedOrigins ?? []).map((value) => value.trim()).filter(Boolean);
const dangerouslyAllowHostHeaderOriginFallback = cfg.gateway?.controlUi?.dangerouslyAllowHostHeaderOriginFallback === true;
assertGatewayAuthConfigured(resolvedAuth, cfg.gateway?.auth);
if (tailscaleMode === "funnel" && authMode !== "password") throw new Error("tailscale funnel requires gateway auth mode=password (set gateway.auth.password or OPENCLAW_GATEWAY_PASSWORD)");
if (isUnsafeGatewayTailscaleNoAuth({
authMode,
tailscaleMode
})) throw new Error(formatUnsafeGatewayTailscaleNoAuthMessage(tailscaleMode));
if (tailscaleMode !== "off" && !isLoopbackHost(bindHost)) throw new Error("tailscale serve/funnel requires gateway bind=loopback (127.0.0.1)");
if (!isLoopbackHost(bindHost) && !hasSharedSecret && authMode !== "trusted-proxy") throw new Error(`refusing to bind gateway to ${bindHost}:${params.port} without auth (set gateway.auth.token/password, or set OPENCLAW_GATEWAY_TOKEN/OPENCLAW_GATEWAY_PASSWORD; legacy CLAWDBOT_* and MOLTBOT_* environment variables are ignored)`);
if (controlUiEnabled && !isLoopbackHost(bindHost) && controlUiAllowedOrigins.length === 0 && !dangerouslyAllowHostHeaderOriginFallback) throw new Error("non-loopback Control UI requires gateway.controlUi.allowedOrigins (set explicit origins), or set gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true to use Host-header origin fallback mode");
if (authMode === "trusted-proxy" && !cfg.gateway?.trustedProxies?.length) throw new Error("gateway auth mode=trusted-proxy requires gateway.trustedProxies to be configured with at least one proxy IP");
}
/** Resolves bind, auth, HTTP, Tailscale, and hook settings for one gateway start. */
async function resolveGatewayRuntimeConfig(params) {
warnLegacyOpenClawEnvVars();
const tailscaleModeEarly = (params.tailscale?.mode ?? params.cfg.gateway?.tailscale?.mode) || "off";
const bindMode = params.bind ?? params.cfg.gateway?.bind ?? (tailscaleModeEarly !== "off" ? "loopback" : defaultGatewayBindMode());
const customBindHost = params.cfg.gateway?.customBindHost;
const bindHost = params.host ?? await resolveGatewayBindHost(bindMode, customBindHost);
if (bindMode === "loopback" && !isLoopbackHost(bindHost)) throw new Error(`gateway bind=loopback resolved to non-loopback host ${bindHost}; refusing fallback to a network bind`);
if (bindMode === "tailnet" && bindHost === "0.0.0.0") throw new Error("gateway bind=tailnet could not resolve a Tailscale or loopback address; refusing wildcard fallback");
if (bindMode === "custom") {
const configuredCustomBindHost = customBindHost?.trim();
if (!configuredCustomBindHost) throw new Error("gateway.bind=custom requires gateway.customBindHost");
if (!isValidIPv4(configuredCustomBindHost)) throw new Error(`gateway.bind=custom requires a valid IPv4 customBindHost (got ${configuredCustomBindHost})`);
if (bindHost !== configuredCustomBindHost) throw new Error(`gateway bind=custom requested ${configuredCustomBindHost} but resolved ${bindHost}; refusing fallback`);
}
const controlUiEnabled = params.controlUiEnabled ?? params.cfg.gateway?.controlUi?.enabled ?? true;
const controlUiBasePath = normalizeControlUiBasePath(params.cfg.gateway?.controlUi?.basePath);
const controlUiRootRaw = params.cfg.gateway?.controlUi?.root;
const controlUiRoot = typeof controlUiRootRaw === "string" && controlUiRootRaw.trim().length > 0 ? controlUiRootRaw.trim() : void 0;
const tailscaleBase = params.cfg.gateway?.tailscale ?? {};
const tailscaleOverrides = params.tailscale ?? {};
const tailscaleConfig = mergeGatewayTailscaleConfig(tailscaleBase, tailscaleOverrides);
const tailscaleMode = tailscaleConfig.mode ?? "off";
const resolvedAuth = resolveGatewayAuth({
authConfig: params.cfg.gateway?.auth,
authOverride: params.auth,
env: process.env,
tailscaleMode
});
const authMode = resolvedAuth.mode;
const hooksConfig = resolveHooksConfig(params.cfg);
const runtimeConfig = {
bindHost,
controlUiEnabled,
controlUiBasePath,
controlUiRoot,
resolvedAuth,
authMode,
tailscaleConfig,
tailscaleMode,
hooksConfig
};
assertGatewayRuntimeSecurityConfig({
...runtimeConfig,
cfg: params.cfg,
port: params.port
});
if (hooksConfig) commitHooksConfigReload();
return runtimeConfig;
}
//#endregion
export { resolveGatewayRuntimeConfig as n, assertGatewayRuntimeSecurityConfig as t };