scheduling: clamp get_logs host-side, and fix two authorization claims
`docs/tools/scheduling.md` said three things about who may do what. Two
were wrong prose; the third was the code.
"All scheduling ops go through the operator approval queue" — one of the
five does. Cancel, edit, list and fire are `require_group("scheduling")`
and nothing else (socket_server/mod.rs:594-643), which is what the MCP
tool descriptions already tell an agent. The page pushed in the cautious
direction: someone watching a runaway recurring schedule would wait for
an operator rather than cancel it themselves.
The authorization sentence covered "read/cancel/edit". Cancel, edit and
fire really do check `cancel_authorized` (self, operator, or subtree) from
three call sites. `handle_list_schedules` takes no requester at all and
returns every row — now stated, along with the part that matters: the
snapshot includes other agents' schedule bodies.
`lines` was documented as "host-capped at 500" and the 500 was in the
agent's own MCP layer, not the host; `handle_get_logs` passed any u32
straight into JournalQuery. A limit in the caller is not a limit, so the
host clamps instead of the sentence changing. That also makes args.rs's
arg doc and the tool description agents read correct, untouched. The
sibling `get_host_journal` already clamps host-side at 100, which is both
the precedent and the control that the missing clamp here was real.
Closes #4230.
This commit is contained in:
parent
bafda6e3d5
commit
c28da210b4
2 changed files with 20 additions and 6 deletions
|
|
@ -3,11 +3,18 @@
|
||||||
## `scheduling` tool group
|
## `scheduling` tool group
|
||||||
|
|
||||||
Scheduled prompts fan a message body out to one or more agent inboxes
|
Scheduled prompts fan a message body out to one or more agent inboxes
|
||||||
at a future time, optionally recurring. All scheduling ops go through
|
at a future time, optionally recurring.
|
||||||
the operator approval queue (even self-targeted schedules — use
|
|
||||||
`remind` for unapproved self-wake). Authorization for read/cancel/edit
|
**Creating** one goes through the operator approval queue, even when it
|
||||||
ops: you can act on schedules you own or any owned by a sub-agent in
|
targets only yourself — use `remind` for an unapproved self-wake. The
|
||||||
your topology subtree.
|
other four verbs need no approval: holding the `scheduling` tool group
|
||||||
|
is the whole gate.
|
||||||
|
|
||||||
|
Authorization for cancel / edit / fire: you can act on schedules you own
|
||||||
|
or any owned by an agent in your topology subtree. **`list_schedules` is
|
||||||
|
not scoped at all** — it returns every schedule on the hive, bodies
|
||||||
|
included, which is what makes it useful for auditing and worth knowing
|
||||||
|
before you put anything private in a schedule body.
|
||||||
|
|
||||||
### `request_schedule_prompt(targets, body, first_fire_at_unix, interval_seconds?, description?)`
|
### `request_schedule_prompt(targets, body, first_fire_at_unix, interval_seconds?, description?)`
|
||||||
|
|
||||||
|
|
@ -55,6 +62,10 @@ and `last_result`, `next_fire_at_unix`, `interval_seconds`. Use to
|
||||||
look up an id before cancelling, or to audit upcoming wake-ups in
|
look up an id before cancelling, or to audit upcoming wake-ups in
|
||||||
your subtree.
|
your subtree.
|
||||||
|
|
||||||
|
Unscoped on purpose — unlike the verbs that _change_ a schedule, this
|
||||||
|
one applies no ownership filter, so the snapshot covers other agents'
|
||||||
|
schedules and the operator's.
|
||||||
|
|
||||||
## `diagnostics` tool group
|
## `diagnostics` tool group
|
||||||
|
|
||||||
### `get_logs(agent, lines?)`
|
### `get_logs(agent, lines?)`
|
||||||
|
|
|
||||||
|
|
@ -1121,7 +1121,10 @@ pub(crate) fn handle_send(
|
||||||
/// `-M` read needs root). `journalctl -M` wants the `h-<name>` machine
|
/// `-M` read needs root). `journalctl -M` wants the `h-<name>` machine
|
||||||
/// name, which `container_name` derives.
|
/// name, which `container_name` derives.
|
||||||
async fn handle_get_logs(agent: &str, lines: Option<u32>) -> Response {
|
async fn handle_get_logs(agent: &str, lines: Option<u32>) -> Response {
|
||||||
let n = lines.unwrap_or(50);
|
// Clamped here and not only in the MCP layer that also clamps it: a
|
||||||
|
// caller-side limit is not a limit, and anything speaking this socket
|
||||||
|
// sets `lines` itself. Mirrors `handle_get_host_journal`'s own cap.
|
||||||
|
let n = lines.unwrap_or(50).min(500);
|
||||||
let machine = crate::lifecycle::container_name(agent);
|
let machine = crate::lifecycle::container_name(agent);
|
||||||
tracing::info!(%agent, %machine, %n, "manager: get_logs");
|
tracing::info!(%agent, %machine, %n, "manager: get_logs");
|
||||||
match crate::priv_client::read_container_journal(
|
match crate::priv_client::read_container_journal(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue