mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 01:29:56 +00:00
## What Problem This Solves Production code still carries duplicated narration over function names, types, branches and CSS selectors. Some of that prose has drifted: Zalo polling is described as development-only even though it is the default production route, and a joined hook helper is called fire-and-forget. ## User Impact No user-visible behavior changes. Runtime logic, templates, CSS declarations, configuration, persisted state, wire formats, public API documentation, licenses and lint-suppression reasons remain intact. ## Why This Change Was Made This maintainer-requested cleanup removes redundant internal helper/registrar summaries, repeated section labels, and obsolete inline font-size history. Existing declarations and shared owners already express these facts; no new abstraction is needed. Comments explaining authority, lifecycle, ordering, cleanup, platform constraints, dependencies and public contracts stay. The measured reduction is 696 net production/tooling lines: 604 standalone comment lines and 92 adjacent blank lines, plus 59 inline comment removals without net line savings. No tests or generated files changed. This is a bounded contextual sweep, not a claim of exhaustive repository coverage; the local census records exact findings, retained candidates, and unread files. Filename-header cleanup from #161768 is excluded. ## Evidence Independent review completed; all accepted documentation findings were addressed by restoring base comments. The remaining changed files are byte-identical to the reviewed and remotely frozen candidate. Blacksmith Testbox validation: - Parser comparison: identical non-comment TypeScript tokens and CSS structure. - Both import-cycle checks: 0 cycles. - Focused existing tests: 40 Vitest shards passed (521.71 seconds). - Plugin contracts: 48 files / 1,153 tests passed. - Plugin, source-to-extension, and SDK/package import-boundary checks passed. - Feishu asset hook check: no build hooks; no plugin browser/control-UI source changed. SDK API comparison passed with no API changes. The full changed-file gate passed remotely. The lowered-threshold duplicate census (12 lines / 80 tokens) completed; its raw 155 records include deliberate probe/fixture matches and are not claimed as removable production code. No tests were added or changed. Public JSDoc was audited independently: the SDK API comparison strips comments, while shipped declarations can preserve them, so API-shape equality alone would not prove documentation preservation. ### Inherited hosted CI failure Exact-head [CI run 36815106181](https://github.com/openclaw/openclaw/actions/runs/36815106181) tested `ff26a4c05d3b41d25477df41cb94010c6cac5cb0` merged with main `75d1f82c18`. The only failing test job was `checks-node-compact-small-19`: `test/helpers/openclaw-test-instance.acquisition.test.ts:33`, “keeps an absent Gateway unreachable while retaining its port claims,” expected `free` but received `busy`. The other failure is the aggregate CI gate. This attempt has 84 successful jobs, 16 skipped jobs, and 88 collateral cancellations; cancelled coverage is not counted as passing. The identical assertion and error were independently verified in [job 110052175838](https://github.com/openclaw/openclaw/actions/runs/36763489663/job/110052175838), the latest attempt (1) for unrelated PR #162070's final head `d07a6981d4`. The acquisition test, instance helper, cleanup wrapper, isolated-state writer, port allocator, claim owner, claim-lock owner and TCP probe are byte-identical between that head and this PR. No changed file participates in the failing acquisition/probe path. The failure precedes Gateway startup; the logs do not identify the competing listener, so no root-cause repair is claimed. Landing uses the maintainer-authorized inherited-failure exception pinned to this exact head, backed by the passing remote gates above. The fixture defect remains with the main-CI coordinator. No workflow rerun, test weakening, timeout increase, or source repush was used to obtain green. GitHub's GraphQL writer rejected auto-merge because its quota was exhausted; the request was reconciled as absent before selecting the supported REST squash path.
61 lines
2.1 KiB
TypeScript
61 lines
2.1 KiB
TypeScript
#!/usr/bin/env node
|
|
|
|
// Ensures webhook handlers authenticate before reading request bodies.
|
|
import path from "node:path";
|
|
import * as ts from "typescript/unstable/ast";
|
|
import { bundledPluginCallsite, bundledPluginFile } from "./lib/bundled-plugin-paths.mjs";
|
|
import { runCallsiteGuard } from "./lib/callsite-guard.mts";
|
|
import {
|
|
collectCallExpressionLines,
|
|
runAsScript,
|
|
unwrapExpression,
|
|
} from "./lib/ts-guard-utils.mts";
|
|
|
|
const sourceRoots = ["extensions"];
|
|
const enforcedFiles = new Set([
|
|
bundledPluginFile("feishu", "src/monitor.transport.ts"),
|
|
bundledPluginFile("googlechat", "src/monitor.ts"),
|
|
bundledPluginFile("zalo", "src/monitor.webhook.ts"),
|
|
]);
|
|
const blockedCallees = new Set(["readJsonBodyWithLimit", "readRequestBodyWithLimit"]);
|
|
const allowedCallsites = new Set([
|
|
// Feishu signs the exact wire body, so this handler must read raw bytes before parsing JSON.
|
|
bundledPluginCallsite("feishu", "src/monitor.transport.ts", 199),
|
|
]);
|
|
|
|
function getCalleeName(expression: ts.Expression): string | null {
|
|
const callee = unwrapExpression(expression);
|
|
if (ts.isIdentifier(callee)) {
|
|
return callee.text;
|
|
}
|
|
if (ts.isPropertyAccessExpression(callee)) {
|
|
return callee.name.text;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function findBlockedWebhookBodyReadLines(
|
|
_content: string,
|
|
_fileName: string,
|
|
sourceFile: ts.SourceFile,
|
|
): number[] {
|
|
return collectCallExpressionLines(sourceFile, (node) => {
|
|
const calleeName = getCalleeName(node.expression);
|
|
return calleeName && blockedCallees.has(calleeName) ? node.expression : null;
|
|
});
|
|
}
|
|
|
|
async function main() {
|
|
await runCallsiteGuard({
|
|
importMetaUrl: import.meta.url,
|
|
sourceRoots,
|
|
findCallLines: findBlockedWebhookBodyReadLines,
|
|
skipRelativePath: (relPath) => !enforcedFiles.has(relPath.replaceAll(path.sep, "/")),
|
|
allowCallsite: (callsite) => allowedCallsites.has(callsite),
|
|
header: "Found forbidden low-level body reads in auth-sensitive webhook handlers:",
|
|
footer:
|
|
"Use plugin-sdk webhook guards (`readJsonWebhookBodyOrReject` / `readWebhookBodyOrReject`) with explicit pre-auth/post-auth profiles.",
|
|
});
|
|
}
|
|
|
|
runAsScript(import.meta.url, main);
|