codex: support hooks in config.toml and requirements.toml (#18893)

## Summary

Support the existing hooks schema in inline TOML so hooks can be
configured from both `config.toml` and enterprise-managed
`requirements.toml` without requiring a separate `hooks.json` payload.

This gives enterprise admins a way to ship managed hook policy through
the existing requirements channel while still leaving script delivery to
MDM or other device-management tooling, and it keeps `hooks.json`
working unchanged for existing users.

This also lays the groundwork for follow-on managed filtering work such
as #15937, while continuing to respect project trust gating from #14718.
It does **not** implement `allow_managed_hooks_only` itself.

NOTE: yes, it's a bit unfortunate that the toml isn't formatted as
closely as normal to our default styling. This is because we're trying
to stay compatible with the spec for plugins/hooks that we'll need to
support & the main usecase here is embedding into requirements.toml

## What changed

- moved the shared hook serde model out of `codex-rs/hooks` into
`codex-rs/config` so the same schema can power `hooks.json`, inline
`config.toml` hooks, and managed `requirements.toml` hooks
- added `hooks` support to both `ConfigToml` and
`ConfigRequirementsToml`, including requirements-side `managed_dir` /
`windows_managed_dir`
- treated requirements-managed hooks as one constrained value via
`Constrained`, so managed hook policy is merged atomically and cannot
drift across requirement sources
- updated hook discovery to load requirements-managed hooks first, then
per-layer `hooks.json`, then per-layer inline TOML hooks, with a warning
when a single layer defines both representations
- threaded managed hook metadata through discovered handlers and exposed
requirements hooks in app-server responses, generated schemas, and
`/debug-config`
- added hook/config coverage in `codex-rs/config`, `codex-rs/hooks`,
`codex-rs/core/src/config_loader/tests.rs`, and
`codex-rs/core/tests/suite/hooks.rs`

## Testing

- `cargo test -p codex-config`
- `cargo test -p codex-hooks`
- `cargo test -p codex-app-server config_api`

## Documentation

Companion updates are needed in the developers website repo for:

- the hooks guide
- the config reference, sample, basic, and advanced pages
- the enterprise managed configuration guide

---------

Co-authored-by: Michael Bolin <mbolin@openai.com>
This commit is contained in:
Andrei Eternal
2026-04-22 21:20:09 -07:00
committed by GitHub
parent 9955eacd22
commit 2b2de3f38b
35 changed files with 2464 additions and 270 deletions

View File

@@ -1172,6 +1172,7 @@ mod tests {
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1203,6 +1204,7 @@ mod tests {
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1234,6 +1236,7 @@ mod tests {
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1282,6 +1285,7 @@ mod tests {
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1366,6 +1370,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1441,6 +1446,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1514,6 +1520,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1714,6 +1721,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1751,6 +1759,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1808,6 +1817,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1860,6 +1870,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1916,6 +1927,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -1973,6 +1985,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -2030,6 +2043,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -2120,6 +2134,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,
@@ -2149,6 +2164,7 @@ enabled = false
allowed_web_search_modes: None,
guardian_policy_config: None,
feature_requirements: None,
hooks: None,
mcp_servers: None,
apps: None,
rules: None,