diff --git a/src/commands/doctor/shared/exec-safe-bins.ts b/src/commands/doctor/shared/exec-safe-bins.ts index 1d9f8a447f8d..196076095778 100644 --- a/src/commands/doctor/shared/exec-safe-bins.ts +++ b/src/commands/doctor/shared/exec-safe-bins.ts @@ -1,3 +1,4 @@ +// Doctor checks and repairs for exec safeBins profiles and trusted binary directories. import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce"; import { sanitizeForLog } from "../../../../packages/terminal-core/src/ansi.js"; import type { OpenClawConfig } from "../../../config/types.openclaw.js"; @@ -15,10 +16,15 @@ import { import { asObjectRecord } from "./object.js"; export type ExecSafeBinCoverageHit = { + /** Config scope that owns the safeBins entry. */ scopePath: string; + /** Normalized binary name from safeBins. */ bin: string; + /** Missing profile coverage or unsafe semantic shape detected by doctor. */ kind: "missingProfile" | "riskySemantics"; + /** True when the missing profile belongs to an interpreter/runtime binary. */ isInterpreter?: boolean; + /** Risk explanation for risky semantic hits. */ warning?: string; }; @@ -31,8 +37,11 @@ type ExecSafeBinScopeRef = { }; export type ExecSafeBinTrustedDirHintHit = { + /** Config scope that owns the safeBins entry. */ scopePath: string; + /** Binary name configured in safeBins. */ bin: string; + /** Resolved executable path outside trusted safe-bin directories. */ resolvedPath: string; }; @@ -112,6 +121,7 @@ function collectExecSafeBinScopes(cfg: OpenClawConfig): ExecSafeBinScopeRef[] { return scopes; } +/** Scan configured safeBins for missing profiles and risky low-friction entries. */ export function scanExecSafeBinCoverage(cfg: OpenClawConfig): ExecSafeBinCoverageHit[] { const hits: ExecSafeBinCoverageHit[] = []; for (const scope of collectExecSafeBinScopes(cfg)) { @@ -139,6 +149,7 @@ export function scanExecSafeBinCoverage(cfg: OpenClawConfig): ExecSafeBinCoverag return hits; } +/** Scan configured safeBins that resolve outside trusted binary directories. */ export function scanExecSafeBinTrustedDirHints( cfg: OpenClawConfig, ): ExecSafeBinTrustedDirHintHit[] { @@ -167,6 +178,7 @@ export function scanExecSafeBinTrustedDirHints( return hits; } +/** Format doctor warnings for safeBins profile coverage and risky semantics. */ export function collectExecSafeBinCoverageWarnings(params: { hits: ExecSafeBinCoverageHit[]; doctorFixCommand: string; @@ -222,6 +234,7 @@ export function collectExecSafeBinCoverageWarnings(params: { return lines; } +/** Format doctor warnings for safeBins resolved outside trusted directories. */ export function collectExecSafeBinTrustedDirHintWarnings( hits: ExecSafeBinTrustedDirHintHit[], ): string[] { @@ -243,6 +256,7 @@ export function collectExecSafeBinTrustedDirHintWarnings( return lines; } +/** Scaffold missing custom safeBin profiles and warn on interpreter/risky entries. */ export function maybeRepairExecSafeBinProfiles(cfg: OpenClawConfig): { config: OpenClawConfig; changes: string[]; diff --git a/src/commands/doctor/shared/hooks-token-reuse-repair.ts b/src/commands/doctor/shared/hooks-token-reuse-repair.ts index afe93eaff5a3..b6b61fde019c 100644 --- a/src/commands/doctor/shared/hooks-token-reuse-repair.ts +++ b/src/commands/doctor/shared/hooks-token-reuse-repair.ts @@ -1,3 +1,4 @@ +// Doctor repair for configs that reuse Gateway shared-secret auth as hooks.token. import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce"; import type { OpenClawConfig } from "../../../config/types.openclaw.js"; import { @@ -18,6 +19,7 @@ function activeGatewaySharedSecret(auth: ResolvedGatewayAuth): string { return ""; } +/** Rotate hooks.token when it matches the active Gateway token/password shared secret. */ export function repairHooksTokenReuseGatewayAuth( cfg: OpenClawConfig, env: NodeJS.ProcessEnv = process.env, diff --git a/src/commands/doctor/shared/invalid-plugin-config.ts b/src/commands/doctor/shared/invalid-plugin-config.ts index cf989b770ae8..14e3fc223a9b 100644 --- a/src/commands/doctor/shared/invalid-plugin-config.ts +++ b/src/commands/doctor/shared/invalid-plugin-config.ts @@ -1,3 +1,4 @@ +// Doctor quarantine for plugin entries whose config fails plugin-aware validation. import { sanitizeForLog } from "../../../../packages/terminal-core/src/ansi.js"; import type { OpenClawConfig } from "../../../config/types.openclaw.js"; import { validateConfigObjectWithPlugins } from "../../../config/validation.js"; @@ -35,6 +36,7 @@ function scanInvalidPluginConfig(cfg: OpenClawConfig): InvalidPluginConfigHit[] return hits; } +/** Disable plugin entries and clear config when plugin validation marks their config invalid. */ export function maybeRepairInvalidPluginConfig(cfg: OpenClawConfig): { config: OpenClawConfig; changes: string[]; diff --git a/src/commands/doctor/shared/legacy-config-compat.ts b/src/commands/doctor/shared/legacy-config-compat.ts index 394638ad4066..3a3b5a57f54e 100644 --- a/src/commands/doctor/shared/legacy-config-compat.ts +++ b/src/commands/doctor/shared/legacy-config-compat.ts @@ -1,6 +1,8 @@ +// Top-level legacy config migration runner used before full config validation. import { applyChannelDoctorCompatibilityMigrations } from "./channel-legacy-config-migrate.js"; import { LEGACY_CONFIG_MIGRATIONS } from "./legacy-config-migrations.js"; +/** Apply all legacy doctor migrations to raw config, returning null when nothing changed. */ export function applyLegacyDoctorMigrations(raw: unknown): { next: Record | null; changes: string[]; diff --git a/src/commands/doctor/shared/legacy-config-compatibility-base.ts b/src/commands/doctor/shared/legacy-config-compatibility-base.ts index 9afee24e0d24..774561b58d7f 100644 --- a/src/commands/doctor/shared/legacy-config-compatibility-base.ts +++ b/src/commands/doctor/shared/legacy-config-compatibility-base.ts @@ -1,3 +1,4 @@ +// Shared base compatibility normalizers reused by core and plugin setup migrations. import type { OpenClawConfig } from "../../../config/types.openclaw.js"; import { normalizeLegacyBrowserConfig, @@ -15,6 +16,7 @@ import { migrateLegacyWebFetchConfig } from "./legacy-web-fetch-migrate.js"; import { migrateLegacyWebSearchConfig } from "./legacy-web-search-migrate.js"; import { migrateLegacyXSearchConfig } from "./legacy-x-search-migrate.js"; +/** Run common compatibility migrations before caller-specific setup/channel passes. */ export function normalizeBaseCompatibilityConfigValues( cfg: OpenClawConfig, changes: string[], diff --git a/src/commands/doctor/shared/legacy-config-core-migrate.ts b/src/commands/doctor/shared/legacy-config-core-migrate.ts index e1f8479c2a34..0b5b7edad9ba 100644 --- a/src/commands/doctor/shared/legacy-config-core-migrate.ts +++ b/src/commands/doctor/shared/legacy-config-core-migrate.ts @@ -1,3 +1,4 @@ +// Core doctor compatibility migration pipeline for current config objects. import type { OpenClawConfig } from "../../../config/types.openclaw.js"; import { runPluginSetupConfigMigrations } from "../../../plugins/setup-registry.js"; import { normalizeAgentId } from "../../../routing/session-key.js"; @@ -42,6 +43,7 @@ function pruneBindingsForMissingAgents(cfg: OpenClawConfig, changes: string[]): }; } +/** Normalize current config through core, plugin setup, channel, and secret-ref migrations. */ export function normalizeCompatibilityConfigValues(cfg: OpenClawConfig): { config: OpenClawConfig; changes: string[];