fix(channels): make the untrusted-turn tool ceiling configurable - #1219
Conversation
|
Heads up for whoever merges: this and #1218 both insert a field into the same spot in |
Greptile SummaryThe PR makes the untrusted-turn tool ceiling configurable per WhatsApp account while preserving fail-closed defaults and the independent
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| crates/channels/src/config_view.rs | Adds shared serialized enums and fail-closed default accessors for untrusted-turn ceilings. |
| crates/gateway/src/channel_events.rs | Resolves account ceilings and applies the selected audience, tool policy, and private-context restrictions. |
| crates/gateway/src/channel_events/dispatch.rs | Integrates account-specific ceilings while retaining the operator-direct-chat shell-command gate. |
| crates/gateway/src/channel_events/tests.rs | Covers default equivalence, independent ceiling axes, and the lifted-ceiling request shape. |
| crates/whatsapp/src/config.rs | Persists and exposes the two new per-account WhatsApp ceiling settings. |
| docs/src/channels.md | Explains how untrusted ceilings interact with channel tool policies and the /sh restriction. |
| docs/src/whatsapp.md | Adds the accepted values and defaults to the WhatsApp account reference. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Inbound channel turn] --> B{Operator in proven direct chat?}
B -->|Yes| C[Use normal tool policy]
B -->|No| D[Load account untrusted ceiling]
D --> E[Apply audience ceiling]
E --> F[Apply deny-all or configured policy]
F --> G[Disable private context]
B -->|No and /sh| H[Reject explicit shell command]
Reviews (2): Last reviewed commit: "fix(channels): make the untrusted-turn t..." | Re-trigger Greptile
moltis-org#1170 gave every turn that is not an operator in a proven direct chat a hardcoded deny-all tool policy on top of the public audience ceiling. That was right for /sh, but it also removed the three tools registered for the public audience, and it made tool policy layers 4 and 5 unreachable in any shared chat, which is the case they were added for in moltis-org#677. Two new per-account fields carry the ceiling instead of hardcoding it: untrusted_audience = "public" | "trusted" (default "public") untrusted_tools = "deny_all" | "policy" (default "deny_all") The defaults reproduce the current behaviour exactly, so an account with no configuration is unchanged. WhatsApp is the only channel that reads them so far; the other eight fall back to the defaults, which is the unconfigured behaviour. /sh keeps its own gate, tied to the operator-direct-chat test and not to the ceiling. It cannot follow the tool policy the way the agent's exec call does: run_explicit_shell_command takes "exec" straight from the request registry, and the [tools.policy] layers are applied in apply_runtime_tool_filters on the agent-run path, which /sh returns before reaching. A guard that widened with the ceiling would hand out an exec that no deny can take back. _private_context stays off for every untrusted turn and is not configurable. Owner memory, profile and project context describe the owner rather than the conversation, so a room with other people in it never receives them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
26432ec to
b05a645
Compare
|
Correction to the original description, and a force-push that fixes it. The first version of this PR gated The first half of that is true and the second half is not. With
Net effect in that configuration: any group member could run shell commands, and a
Also in this push, from the review feedback:
|
|
Updating the earlier merge-order note: this and #1218 now overlap in two files rather than one. Both insert a field after |
|
@greptileai review |
#1170 gave every turn that is not an operator in a proven direct chat a
hardcoded deny-all tool policy on top of the public audience ceiling. That
was right for /sh, but it also removed the three tools registered for the
public audience, and it made tool policy layers 4 and 5 unreachable in any
shared chat, which is the case they were added for in #677.
Two new per-account fields carry the ceiling instead of hardcoding it:
untrusted_audience = "public" | "trusted" (default "public")
untrusted_tools = "deny_all" | "policy" (default "deny_all")
The defaults reproduce the current behaviour exactly, so an account with no
configuration is unchanged. WhatsApp is the only channel that reads them so
far; the other eight fall back to the defaults, which is the unconfigured
behaviour.
/sh keeps its own gate, tied to the operator-direct-chat test and not to the
ceiling. It cannot follow the tool policy the way the agent's exec call does:
run_explicit_shell_command takes "exec" straight from the request registry,
and the [tools.policy] layers are applied in apply_runtime_tool_filters on
the agent-run path, which /sh returns before reaching. A guard that widened
with the ceiling would hand out an exec that no deny can take back.
_private_context stays off for every untrusted turn and is not configurable.
Owner memory, profile and project context describe the owner rather than the
conversation, so a room with other people in it never receives them.
🤖 Generated with Claude Code