swarm-controller: refuse a state transition off destroyed

This commit is contained in:
damocles 2026-09-07 19:44:23 +02:00 committed by mara
commit 79937a1934
2 changed files with 86 additions and 1 deletions

View file

@ -794,7 +794,7 @@ fn declaration_target(
request_body = SetAgentStateRequest,
responses(
(status = 200, description = "the declaration as now published", body = Vec<AgentDeclaration>),
(status = 400, description = "a name is not an identifier, the hive is not in this swarm, or the state is unknown (problem+json)", body = String),
(status = 400, description = "a name is not an identifier, the hive is not in this swarm, the state is unknown, or the agent is already declared destroyed (terminal — problem+json)", body = String),
(status = 503, description = "no swarm queue is wired up (problem+json)", body = String),
(status = 500, description = "the declaration could not be published (problem+json)", body = String),
),
@ -812,6 +812,12 @@ async fn set_agent_state(
.into_string();
let declaration = writer.set(&hive, &agent, req.state).await.map_err(|e| {
// A `TerminalStateError` is the caller's mistake (asking to move an
// agent off a state its own doc comment says is terminal), not a
// server fault — everything else here is the pre-existing catch-all.
if let Some(terminal) = e.downcast_ref::<wanted::TerminalStateError>() {
return error_problem(axum::http::StatusCode::BAD_REQUEST, &terminal.to_string());
}
tracing::warn!(hive = %hive, agent = %agent, error = %format!("{e:#}"), "declaring agent state failed");
error_problem(
axum::http::StatusCode::INTERNAL_SERVER_ERROR,