Watch
0
0
Fork
You've already forked hyperhive
0

remove operator as target for scheduled prompts

This commit is contained in:
damocles 2026-09-11 22:36:40 +02:00 • committed by mara
commit b4dc09ff93
7 changed files with 130 additions and 86 deletions

View file

@ -220,11 +220,21 @@ impl ScheduledPrompts {
/// Insert a new schedule. Returns the new id. Empty `targets` is
/// rejected — a schedule with no recipients would silently
/// never fan out, masking caller bugs.
/// never fan out, masking caller bugs. `operator` is rejected too
/// — it isn't a container with a todo inbox to push a wake into,
/// and scheduling a prompt at the operator herself doesn't fit the
/// "fan a prompt out to agent inboxes" shape this exists for.
pub fn submit(&self, new: &NewSchedule) -> Result<i64> {
if new.targets.is_empty() {
bail!("schedule must have at least one target");
}
if new
.targets
.iter()
.any(|t| t == hive_sh4re::manager::OPERATOR_RECIPIENT)
{
bail!("operator is not a valid schedule target");
}
let mut conn = self.conn.lock().unwrap();
let tx = conn.transaction()?;
tx.execute(
@ -435,6 +445,12 @@ impl ScheduledPrompts {
if let Some(Some(0)) = patch.interval_seconds {
bail!("interval_seconds must be > 0 (use None for one-shot)");
}
if patch.targets_add.as_deref().is_some_and(|list| {
list.iter()
.any(|t| t == hive_sh4re::manager::OPERATOR_RECIPIENT)
}) {
bail!("operator is not a valid schedule target");
}
// Single transaction so a partial failure can't leave a
// half-updated row.
let tx = conn.transaction()?;
@ -747,6 +763,39 @@ mod tests {
assert!(format!("{err:#}").contains("at least one target"));
}
#[test]
fn submit_rejects_operator_as_a_target() {
let (_dir, db) = open();
let err = db
.submit(&NewSchedule {
owner: "operator".into(),
targets: vec!["operator".into()],
body: "wake".into(),
first_fire_at_unix: 100,
interval_seconds: None,
description: None,
source: ScheduleSource::Operator,
})
.unwrap_err();
assert!(format!("{err:#}").contains("operator is not a valid schedule target"));
}
#[test]
fn update_rejects_operator_in_targets_add() {
let (_dir, db) = open();
let id = submit_one_shot(&db, 100, &["alice"]);
let err = db
.update(
id,
UpdateSchedule {
targets_add: Some(vec!["operator".into()]),
..Default::default()
},
)
.unwrap_err();
assert!(format!("{err:#}").contains("operator is not a valid schedule target"));
}
#[test]
fn due_returns_only_past_active_rows() {
let (_dir, db) = open();