mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-03 03:03:24 -04:00
fix(config): allow root without zod preprocess wrapper
This commit is contained in:
@@ -61,7 +61,7 @@ See the [full reference](/gateway/configuration-reference) for every available f
|
||||
## Strict validation
|
||||
|
||||
<Warning>
|
||||
OpenClaw only accepts configurations that fully match the schema. Unknown keys, malformed types, or invalid values cause the Gateway to **refuse to start**.
|
||||
OpenClaw only accepts configurations that fully match the schema. Unknown keys, malformed types, or invalid values cause the Gateway to **refuse to start**. The only root-level exception is `$schema` (string), so editors can attach JSON Schema metadata.
|
||||
</Warning>
|
||||
|
||||
When validation fails:
|
||||
|
||||
@@ -11,7 +11,7 @@ title: "Strict Config Validation"
|
||||
|
||||
## Goals
|
||||
|
||||
- **Reject unknown config keys everywhere** (root + nested).
|
||||
- **Reject unknown config keys everywhere** (root + nested), except root `$schema` metadata.
|
||||
- **Reject plugin config without a schema**; don’t load that plugin.
|
||||
- **Remove legacy auto-migration on load**; migrations run via doctor only.
|
||||
- **Auto-run doctor (dry-run) on startup**; if invalid, block non-diagnostic commands.
|
||||
@@ -24,7 +24,7 @@ title: "Strict Config Validation"
|
||||
## Strict validation rules
|
||||
|
||||
- Config must match the schema exactly at every level.
|
||||
- Unknown keys are validation errors (no passthrough at root or nested).
|
||||
- Unknown keys are validation errors (no passthrough at root or nested), except root `$schema` when it is a string.
|
||||
- `plugins.entries.<id>.config` must be validated by the plugin’s schema.
|
||||
- If a plugin lacks a schema, **reject plugin load** and surface a clear error.
|
||||
- Unknown `channels.<id>` keys are errors unless a plugin manifest declares the channel id.
|
||||
|
||||
@@ -7,15 +7,8 @@ describe("$schema key in config (#14998)", () => {
|
||||
$schema: "https://openclaw.ai/config.json",
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
});
|
||||
|
||||
it("strips $schema from parsed output so it does not leak into UI", () => {
|
||||
const result = OpenClawSchema.safeParse({
|
||||
$schema: "https://openclaw.ai/config.json",
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
if (result.success) {
|
||||
expect("$schema" in result.data).toBe(false);
|
||||
expect(result.data.$schema).toBe("https://openclaw.ai/config.json");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -24,8 +17,8 @@ describe("$schema key in config (#14998)", () => {
|
||||
expect(result.success).toBe(true);
|
||||
});
|
||||
|
||||
it("ignores non-string $schema (stripped before validation)", () => {
|
||||
it("rejects non-string $schema", () => {
|
||||
const result = OpenClawSchema.safeParse({ $schema: 123 });
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ describe("config schema", () => {
|
||||
const schema = res.schema as { properties?: Record<string, unknown> };
|
||||
expect(schema.properties?.gateway).toBeTruthy();
|
||||
expect(schema.properties?.agents).toBeTruthy();
|
||||
expect(schema.properties?.$schema).toBeUndefined();
|
||||
expect(res.uiHints.gateway?.label).toBe("Gateway");
|
||||
expect(res.uiHints["gateway.auth.token"]?.sensitive).toBe(true);
|
||||
expect(res.version).toBeTruthy();
|
||||
|
||||
@@ -303,6 +303,12 @@ function stripChannelSchema(schema: ConfigSchema): ConfigSchema {
|
||||
if (!root || !root.properties) {
|
||||
return next;
|
||||
}
|
||||
// Allow `$schema` in config files for editor tooling, but hide it from the
|
||||
// Control UI form schema so it does not show up as a configurable section.
|
||||
delete root.properties.$schema;
|
||||
if (Array.isArray(root.required)) {
|
||||
root.required = root.required.filter((key) => key !== "$schema");
|
||||
}
|
||||
const channelsNode = asSchemaObject(root.properties.channels);
|
||||
if (channelsNode) {
|
||||
channelsNode.properties = {};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user