deny unknown fields and add docs

This commit is contained in:
Sayan Sisodiya
2026-01-09 19:43:39 -08:00
parent d47b85d9fe
commit eede02a5ef
8 changed files with 81 additions and 25 deletions
+12
View File
@@ -0,0 +1,12 @@
# Config JSON Schema
We generate a JSON Schema for `~/.codex/config.toml` from the `ConfigToml` type
and commit it at `docs/config.schema.json` for editor integration.
When you change any fields included in `ConfigToml` (or nested config types),
regenerate the schema and update the fixture:
```
just write-config-schema
cargo test -p codex-core config_schema_matches_fixture
```
+8
View File
@@ -684,8 +684,13 @@ pub fn set_default_oss_provider(codex_home: &Path, provider: &str) -> std::io::R
}
/// Base config deserialized from ~/.codex/config.toml.
// The JSON Schema in `docs/config.schema.json` is generated from this struct.
// If you add, remove, or rename fields, regenerate the schema via
// `just write-config-schema` and update the fixture test.
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct ConfigToml {
pub test: Option<String>,
/// Optional override of model selection.
pub model: Option<String>,
/// Review model override used by the `/review` feature.
@@ -886,6 +891,7 @@ impl From<ConfigToml> for UserSavedConfig {
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct ProjectConfig {
pub trust_level: Option<TrustLevel>,
}
@@ -901,6 +907,7 @@ impl ProjectConfig {
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct ToolsToml {
#[serde(default, alias = "web_search_request")]
pub web_search: Option<bool>,
@@ -920,6 +927,7 @@ impl From<ToolsToml> for Tools {
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct GhostSnapshotToml {
/// Exclude untracked files larger than this many bytes from ghost snapshots.
#[serde(alias = "ignore_untracked_files_over_bytes")]
+1
View File
@@ -12,6 +12,7 @@ use codex_protocol::openai_models::ReasoningEffort;
/// Collection of common configuration options that a user can define as a unit
/// in `config.toml`.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct ConfigProfile {
pub model: Option<String>,
/// The key in the `model_providers` map identifying the
+8 -2
View File
@@ -48,7 +48,7 @@ pub(crate) fn features_schema(schema_gen: &mut SchemaGenerator) -> Schema {
.properties
.insert(feature.key.to_string(), schema_gen.subschema_for::<bool>());
}
validation.additional_properties = Some(Box::new(schema_gen.subschema_for::<bool>()));
validation.additional_properties = Some(Box::new(Schema::Bool(false)));
object.object = Some(Box::new(validation));
Schema::Object(object)
@@ -84,6 +84,7 @@ fn mcp_server_schema(schema_gen: &mut SchemaGenerator) -> Schema {
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[schemars(deny_unknown_fields)]
struct McpServerStdioSchema {
command: String,
#[serde(default)]
@@ -109,6 +110,7 @@ struct McpServerStdioSchema {
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[schemars(deny_unknown_fields)]
struct McpServerStreamableHttpSchema {
url: String,
#[serde(default)]
@@ -145,9 +147,13 @@ mod tests {
let fixture = std::fs::read_to_string(fixture_path).expect("read config schema fixture");
let fixture_value: serde_json::Value =
serde_json::from_str(&fixture).expect("parse config schema fixture");
assert_eq!(fixture_value, schema_value);
assert_eq!(
fixture_value, schema_value,
"Current schema for `config.toml` doesn't match the fixture. Run `just write-config-schema` to overwrite with your changes."
);
}
/// Overwrite the config schema fixture with the current schema.
#[test]
#[ignore]
fn write_config_schema_fixture() {
+9
View File
@@ -256,6 +256,7 @@ impl UriBasedFileOpener {
/// Settings that govern if and what will be written to `~/.codex/history.jsonl`.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct History {
/// If true, history entries will not be written to disk.
pub persistence: HistoryPersistence,
@@ -279,6 +280,7 @@ pub enum HistoryPersistence {
/// Analytics settings loaded from config.toml. Fields are optional so we can apply defaults.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct AnalyticsConfigToml {
/// When `false`, disables analytics across Codex product surfaces in this profile.
pub enabled: Option<bool>,
@@ -302,6 +304,7 @@ pub enum OtelHttpProtocol {
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
#[serde(rename_all = "kebab-case")]
pub struct OtelTlsConfig {
pub ca_certificate: Option<AbsolutePathBuf>,
@@ -311,6 +314,7 @@ pub struct OtelTlsConfig {
/// Which OTEL exporter to use.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
#[schemars(deny_unknown_fields)]
#[serde(rename_all = "kebab-case")]
pub enum OtelExporterKind {
None,
@@ -334,6 +338,7 @@ pub enum OtelExporterKind {
/// OTEL settings loaded from config.toml. Fields are optional so we can apply defaults.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct OtelConfigToml {
/// Log user prompt in traces
pub log_user_prompt: Option<bool>,
@@ -407,6 +412,7 @@ impl Default for ScrollInputMode {
/// Collection of settings that are specific to the TUI.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct Tui {
/// Enable desktop notifications from the TUI when the terminal is unfocused.
/// Defaults to `true`.
@@ -546,6 +552,7 @@ const fn default_true() -> bool {
/// (primarily the Codex IDE extension). NOTE: these are different from
/// notifications - notices are warnings, NUX screens, acknowledgements, etc.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct Notice {
/// Tracks whether the user has acknowledged the full access warning prompt.
pub hide_full_access_warning: Option<bool>,
@@ -569,6 +576,7 @@ impl Notice {
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct SandboxWorkspaceWrite {
#[serde(default)]
pub writable_roots: Vec<AbsolutePathBuf>,
@@ -609,6 +617,7 @@ pub enum ShellEnvironmentPolicyInherit {
/// Policy for building the `env` when spawning a process via either the
/// `shell` or `local_shell` tool.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct ShellEnvironmentPolicyToml {
pub inherit: Option<ShellEnvironmentPolicyInherit>,
+1
View File
@@ -50,6 +50,7 @@ pub enum WireApi {
/// Serializable representation of a provider definition.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct ModelProviderInfo {
/// Friendly display name.
pub name: String,