Files
openclaw/src/config/future-version-guard.ts
T
Peter Steinberger edecdbd05e refactor(config): config-surface reduction tranche 3 — product consolidations (review request) (#111527)
* refactor(config): consolidate media model lists

* refactor(config): unify memory configuration

* refactor(config): consolidate TTS ownership

* refactor(config): move typing policy to agents

* refactor(config): retire product-level config surfaces

* refactor(config): share scoped tool policy type

* chore(config): refresh generated baselines

* fix(config): honor agent typing overrides

* fix(config): migrate sibling config consumers

* refactor(infra): keep base64url decoder private

* fix(config): strip invalid legacy TTS values

* chore(config): refresh rebased baseline hash

* fix(doctor): route legacy messages.tts.realtime voice to talk during tts move

* refactor(config): polish final layout names

* refactor(config): freeze retired tuning defaults

* feat(config): add fast mode default symmetry

* refactor(config): key agent entries by id

* docs(config): update final layout reference

* test(config): cover final layout migrations

* chore(config): refresh final layout baselines

* fix(config): align final layout runtime readers

* fix(config): align remaining readers

* fix(config): stabilize final layout migrations

* fix(config): finalize config projection proof

* fix(config): address final layout review

* docs(release): preserve historical config names

* fix(config): complete keyed agent migration

* fix(config): close final migration gaps

* fix(config): finish full-branch review

* fix(config): complete runtime secret detection

* fix(config): close final review findings

* fix(config): finish canonical docs and heartbeat migration

* fix(config): integrate latest main after rebase

* refactor(env): isolate test-only controls

* refactor(env): isolate build and development controls

* refactor(env): collapse process identity indirection

* refactor(env): remove duplicate config and temp aliases

* docs(env): define the operator-facing allowlist

* ci(env): ratchet production variable count

* fix(env): remove stale provider helper import

* fix(env): make ratchet sorting explicit

* test(env): keep test seam in dead-code audit

* test(env): cover ratchet growth and boundary; document surface budgets

* docs(config): document tier-eval consolidations

* docs(config): clarify speech preference ownership

* test(memory): align retired tuning fixtures

* refactor(memory): freeze engine heuristics

* refactor(config): apply tier-eval tranche

* refactor(tts): move persona shaping to providers

* refactor(compaction): move prompt policy to providers

* test(config): align hookified prompt fixtures

* chore(deadcode): classify test-only exports

* chore(github): remove unused spawn helper

* chore(deadcode): classify queue diagnostics

* chore(deadcode): remove unused lane snapshot export

* chore(plugin-sdk): ratchet consolidated surface

* fix(config): integrate latest main after rebase
2026-07-21 20:28:43 -07:00

83 lines
3.0 KiB
TypeScript

// Rejects config files written by unsupported future versions.
import { VERSION } from "../version.js";
import type { ConfigFileSnapshot, OpenClawConfig } from "./types.js";
import { shouldWarnOnTouchedVersion } from "./version.js";
/** Override env var for intentional older-binary destructive config actions. */
export const ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS_ENV =
"OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS";
/** Block payload shown when an older binary would mutate newer-written config. */
export type FutureConfigActionBlock = {
action: string;
currentVersion: string;
touchedVersion: string;
message: string;
hints: string[];
};
type FutureConfigGuardParams = {
action: string;
snapshot?: Pick<ConfigFileSnapshot, "config" | "sourceConfig"> | null;
config?: OpenClawConfig | null;
currentVersion?: string;
env?: Record<string, string | undefined>;
};
function allowOlderBinaryDestructiveActions(env: Record<string, string | undefined>): boolean {
const raw = env[ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS_ENV]?.trim().toLowerCase();
return raw === "1" || raw === "true" || raw === "yes";
}
function resolveTouchedVersion(params: FutureConfigGuardParams): string | null {
const readSourceVersion = (value: unknown): string | undefined => {
if (!value || typeof value !== "object") {
return undefined;
}
const meta = (value as { meta?: unknown }).meta;
if (!meta || typeof meta !== "object") {
return undefined;
}
const version = (meta as { lastTouchedVersion?: unknown }).lastTouchedVersion;
return typeof version === "string" ? version.trim() || undefined : undefined;
};
return (
readSourceVersion(params.snapshot?.sourceConfig) ??
readSourceVersion(params.snapshot?.config) ??
readSourceVersion(params.config) ??
null
);
}
/** Resolves whether a destructive action should be blocked by future config metadata. */
export function resolveFutureConfigActionBlock(
params: FutureConfigGuardParams,
): FutureConfigActionBlock | null {
const env = params.env ?? process.env;
if (allowOlderBinaryDestructiveActions(env)) {
return null;
}
const currentVersion = params.currentVersion ?? VERSION;
const touchedVersion = resolveTouchedVersion(params);
if (!touchedVersion || !shouldWarnOnTouchedVersion(currentVersion, touchedVersion)) {
return null;
}
return {
action: params.action,
currentVersion,
touchedVersion,
message: `Refusing to ${params.action} because this OpenClaw binary (${currentVersion}) is older than the config last written by OpenClaw ${touchedVersion}.`,
hints: [
"Run the newer openclaw binary on PATH, or reinstall the intended gateway service from the newer install.",
`Set ${ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS_ENV}=1 only for an intentional downgrade or recovery action.`,
],
};
}
/** Formats a future-config action block for CLI/service error output. */
export function formatFutureConfigActionBlock(block: FutureConfigActionBlock): string {
return [block.message, ...block.hints].join("\n");
}