mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-28 19:53:38 +00:00
refactor(config): dedupe observe suspicion checks
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
persistBoundedClobberedConfigSnapshot,
|
||||
persistBoundedClobberedConfigSnapshotSync,
|
||||
} from "./io.clobber-snapshot.js";
|
||||
import { resolveConfigObserveSuspiciousReasons } from "./io.observe-suspicious.js";
|
||||
import { formatConfigIssueSummary } from "./issue-format.js";
|
||||
import { resolveStateDir } from "./paths.js";
|
||||
import {
|
||||
@@ -510,49 +511,6 @@ function createBackupRestoreAuditAppendParams(params: {
|
||||
});
|
||||
}
|
||||
|
||||
function isUpdateChannelOnlyRoot(value: unknown): boolean {
|
||||
if (!isRecord(value)) {
|
||||
return false;
|
||||
}
|
||||
const keys = Object.keys(value);
|
||||
if (keys.length !== 1 || keys[0] !== "update") {
|
||||
return false;
|
||||
}
|
||||
const update = value.update;
|
||||
if (!isRecord(update)) {
|
||||
return false;
|
||||
}
|
||||
const updateKeys = Object.keys(update);
|
||||
return updateKeys.length === 1 && typeof update.channel === "string";
|
||||
}
|
||||
|
||||
function resolveConfigObserveSuspiciousReasons(params: {
|
||||
bytes: number;
|
||||
hasMeta: boolean;
|
||||
gatewayMode: string | null;
|
||||
parsed: unknown;
|
||||
lastKnownGood?: ConfigHealthFingerprint;
|
||||
}): string[] {
|
||||
const reasons: string[] = [];
|
||||
const baseline = params.lastKnownGood;
|
||||
if (!baseline) {
|
||||
return reasons;
|
||||
}
|
||||
if (baseline.bytes >= 512 && params.bytes < Math.floor(baseline.bytes * 0.5)) {
|
||||
reasons.push(`size-drop-vs-last-good:${baseline.bytes}->${params.bytes}`);
|
||||
}
|
||||
if (baseline.hasMeta && !params.hasMeta) {
|
||||
reasons.push("missing-meta-vs-last-good");
|
||||
}
|
||||
if (baseline.gatewayMode && !params.gatewayMode) {
|
||||
reasons.push("gateway-mode-missing-vs-last-good");
|
||||
}
|
||||
if (baseline.gatewayMode && isUpdateChannelOnlyRoot(params.parsed)) {
|
||||
reasons.push("update-channel-only-root");
|
||||
}
|
||||
return reasons;
|
||||
}
|
||||
|
||||
function resolveSuspiciousSignature(
|
||||
current: ConfigHealthFingerprint,
|
||||
suspicious: string[],
|
||||
|
||||
50
src/config/io.observe-suspicious.ts
Normal file
50
src/config/io.observe-suspicious.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { isRecord } from "../utils.js";
|
||||
|
||||
export type ConfigObserveSuspiciousBaseline = {
|
||||
bytes: number;
|
||||
hasMeta: boolean;
|
||||
gatewayMode: string | null;
|
||||
};
|
||||
|
||||
function isUpdateChannelOnlyRoot(value: unknown): boolean {
|
||||
if (!isRecord(value)) {
|
||||
return false;
|
||||
}
|
||||
const keys = Object.keys(value);
|
||||
if (keys.length !== 1 || keys[0] !== "update") {
|
||||
return false;
|
||||
}
|
||||
const update = value.update;
|
||||
if (!isRecord(update)) {
|
||||
return false;
|
||||
}
|
||||
const updateKeys = Object.keys(update);
|
||||
return updateKeys.length === 1 && typeof update.channel === "string";
|
||||
}
|
||||
|
||||
export function resolveConfigObserveSuspiciousReasons(params: {
|
||||
bytes: number;
|
||||
hasMeta: boolean;
|
||||
gatewayMode: string | null;
|
||||
parsed: unknown;
|
||||
lastKnownGood?: ConfigObserveSuspiciousBaseline;
|
||||
}): string[] {
|
||||
const reasons: string[] = [];
|
||||
const baseline = params.lastKnownGood;
|
||||
if (!baseline) {
|
||||
return reasons;
|
||||
}
|
||||
if (baseline.bytes >= 512 && params.bytes < Math.floor(baseline.bytes * 0.5)) {
|
||||
reasons.push(`size-drop-vs-last-good:${baseline.bytes}->${params.bytes}`);
|
||||
}
|
||||
if (baseline.hasMeta && !params.hasMeta) {
|
||||
reasons.push("missing-meta-vs-last-good");
|
||||
}
|
||||
if (baseline.gatewayMode && !params.gatewayMode) {
|
||||
reasons.push("gateway-mode-missing-vs-last-good");
|
||||
}
|
||||
if (baseline.gatewayMode && isUpdateChannelOnlyRoot(params.parsed)) {
|
||||
reasons.push("update-channel-only-root");
|
||||
}
|
||||
return reasons;
|
||||
}
|
||||
@@ -70,6 +70,7 @@ import {
|
||||
promoteConfigSnapshotToLastKnownGood as promoteConfigSnapshotToLastKnownGoodWithDeps,
|
||||
recoverConfigFromLastKnownGood as recoverConfigFromLastKnownGoodWithDeps,
|
||||
} from "./io.observe-recovery.js";
|
||||
import { resolveConfigObserveSuspiciousReasons } from "./io.observe-suspicious.js";
|
||||
import { retainGeneratedOwnerDisplaySecret } from "./io.owner-display-secret.js";
|
||||
import {
|
||||
collectChangedPaths,
|
||||
@@ -638,49 +639,6 @@ function setConfigHealthEntry(
|
||||
};
|
||||
}
|
||||
|
||||
function isUpdateChannelOnlyRoot(value: unknown): boolean {
|
||||
if (!isRecord(value)) {
|
||||
return false;
|
||||
}
|
||||
const keys = Object.keys(value);
|
||||
if (keys.length !== 1 || keys[0] !== "update") {
|
||||
return false;
|
||||
}
|
||||
const update = value.update;
|
||||
if (!isRecord(update)) {
|
||||
return false;
|
||||
}
|
||||
const updateKeys = Object.keys(update);
|
||||
return updateKeys.length === 1 && typeof update.channel === "string";
|
||||
}
|
||||
|
||||
function resolveConfigObserveSuspiciousReasons(params: {
|
||||
bytes: number;
|
||||
hasMeta: boolean;
|
||||
gatewayMode: string | null;
|
||||
parsed: unknown;
|
||||
lastKnownGood?: ConfigHealthFingerprint;
|
||||
}): string[] {
|
||||
const reasons: string[] = [];
|
||||
const baseline = params.lastKnownGood;
|
||||
if (!baseline) {
|
||||
return reasons;
|
||||
}
|
||||
if (baseline.bytes >= 512 && params.bytes < Math.floor(baseline.bytes * 0.5)) {
|
||||
reasons.push(`size-drop-vs-last-good:${baseline.bytes}->${params.bytes}`);
|
||||
}
|
||||
if (baseline.hasMeta && !params.hasMeta) {
|
||||
reasons.push("missing-meta-vs-last-good");
|
||||
}
|
||||
if (baseline.gatewayMode && !params.gatewayMode) {
|
||||
reasons.push("gateway-mode-missing-vs-last-good");
|
||||
}
|
||||
if (baseline.gatewayMode && isUpdateChannelOnlyRoot(params.parsed)) {
|
||||
reasons.push("update-channel-only-root");
|
||||
}
|
||||
return reasons;
|
||||
}
|
||||
|
||||
async function readConfigFingerprintForPath(
|
||||
deps: Required<ConfigIoDeps>,
|
||||
targetPath: string,
|
||||
|
||||
Reference in New Issue
Block a user