A control that is switched on is not the same as a control that is enforcing.
Every layer below is configured, live, and — under a specific documented condition — inert. Each entry names the condition, the party that owns it, and the structural close. Where no close exists, the entry says so, because an accepted residual is a governance artifact and a hand-waved one is a finding.
Verified against first-party Anthropic documentation on 7 August 2026. Inference hooks are in beta and Anthropic notes that field names, request shapes, and headers may change; treat the server-side entries as current to that date and re-verify before an audit.
Server-side: five conditions
Transcripts are sent untruncated up to 10 MB. Anthropic names the trap directly: nginx defaults to a 1 MB body limit and Express to roughly 100 kB, a rejected body counts as a webhook failure, and under fail-open the prompt reaches the model uninspected. The largest transcripts — the ones most likely to carry bulk regulated material — are the ones most likely to skip inspection. Owner: customer. Close: raise the body limit to 10 MB and set failure handling to block. This is the likeliest real-world failure in the entire integration.
A rollout percentage inspects a chosen fraction of requests. Requests outside the sample proceed uninspected even where the failure mode is set to block. Owner: customer. Close: 100 percent, with shadow mode rather than partial rollout as the tuning instrument, since shadow mode observes every request without blocking any.
Exclusions exempt members of chosen roles entirely. Two mitigating details are documented and worth crediting: traffic authenticated by machine credentials is always inspected, and when role membership cannot be resolved the request fails closed. Owner: customer. Close: none available beyond removing the exclusion — this is a deliberate exemption, and it belongs on a risk register with an owner and a review date rather than in a configuration file.
Anthropic’s forward-compatibility guidance instructs integrators to return allow when the top-level type is unrecognized, because returning an error counts as a webhook failure and sustained failures trip the circuit breaker. The instruction is sound engineering and its security consequence should be stated plainly: when response-side enforcement ships as a new event, correctly written existing servers will allow it by default. Owner: shared. Close: none structural. Track the event roster as a change-management item, not a configuration one.
Raw file and image bytes never reach the security server. A screenshot of a regulated document is not inspected. Owner: shared. Close: none within this instrument. Endpoint and browser controls remain in scope for that path — the hook narrows the text channel rather than closing every channel. Worth stating both readings together, because they travel separately: the byte exclusion is a genuine privacy assurance and a genuine coverage gap, and launch material has occasion to carry only the first.
Client-side: three conditions
Exit code 2 blocks; any other non-zero exit is a non-blocking error and execution continues. HTTP handlers cannot signal a block by status code at all — a non-2xx response, a connection failure, or a timeout is a non-blocking error. Owner: customer. Close: do not use a hook as the hard allow-or-deny. Anthropic’s own reference directs architects to the permission system for that, and a managed deny rule cannot be overridden by any settings scope or command-line flag.
The if filter is best-effort and fails open on unparseable commands. Owner: customer. Close: same as above — the permission layer, not the hook, carries hard enforcement.
Hooks can be defined at user, project, local, managed, plugin, and skill or agent level. Owner: customer. Close: fully available and often unused. allowManagedHooksOnly restricts loading to managed hooks, SDK hooks, and hooks from plugins force-enabled in managed settings. allowedHttpHookUrls constrains HTTP handler destinations, with an empty array blocking all HTTP hooks. httpHookAllowedEnvVars intersects with each hook’s own allowlist. disableBypassPermissionsMode closes the permission-skipping mode. And forceRemoteSettingsRefresh blocks CLI startup until managed settings are freshly fetched, exiting rather than proceeding on stale or absent policy — fail-closed policy delivery, which completes the client-side picture.
Shared: the condition neither layer covers
The inference hook’s verdict acts on what enters the model, and by the time a frame carrying a tool call is evaluated, the tool has already run. The client-side write boundary does refuse tool calls — but only inside Claude Code. On every other governed surface, no configured layer refuses an action. Owner: shared. Close: none currently. This is the residual, and it should be stated to a risk committee in exactly these terms rather than absorbed into a coverage percentage.
Two operational realities that are not gaps
Neither is a hole in coverage; both belong in the same conversation because both determine whether the layer is running at all.
The enforcement layer is a production dependency with a manual reset. Sustained failures trip a circuit breaker that halts enforcement entirely, after which failure handling applies to every request and an administrator must re-enable verdicts by hand. Under fail-closed, the organization is blocked until a human acts. That is the correct trade and it needs an on-call owner.
The health panel is best-effort. Anthropic documents that it reports zero failures when counters cannot be read. A healthy panel is therefore not evidence of a healthy server. Stating that in the documentation rather than leaving it to be discovered is the kind of disclosure that should be credited.
The hard claim
Every entry above is a documented condition, not a defect. What separates the nine is not severity but whether a close exists: five close structurally with configuration the customer already holds, and four do not close within these instruments at all.
Which means the interesting number for a risk committee is not how many layers are switched on. It is how many of the nine have a named owner and a dated decision behind them. That count is producible on demand. A coverage percentage is not.
This closes the hooks pair. The series returns to the write path.
Five of the nine close with configuration the enterprise already holds. Four do not close at all, and carrying them as accepted residuals is a governance act, not a gap in the work.
The measure of assurance is not how many layers are enabled. It is how many of these nine carry a named owner and a dated decision — a count that is producible on demand, where a coverage percentage is not.
