diff --git a/swarm-controller/src/main.rs b/swarm-controller/src/main.rs index 57ed689f..0e939810 100644 --- a/swarm-controller/src/main.rs +++ b/swarm-controller/src/main.rs @@ -810,19 +810,27 @@ async fn get_agent_config_pr( /// scale and isn't how the rest of swarm-ui's single-fetch pages (jobq, /// hives status) work. /// +/// Deliberately **not** `/api/agents/config-prs`: agent names are +/// user-specified (any string `hive_types::Ident` accepts), so a literal +/// path segment sitting where a `{name}` capture could plausibly also want +/// to live is a real, not theoretical, clash risk the moment someone names +/// an agent `config-prs` — per mara's review call, closed off by +/// construction rather than relying on axum's static-route-priority +/// tiebreak to paper over it. +/// /// Only agents with a currently-open PR are present — same "absence is the /// answer" shape [`get_agent_config_pr`]'s `null` uses, just at map-entry /// granularity instead of per-request. #[utoipa::path( get, - path = "/api/agents/config-prs", + path = "/api/config-prs", responses( (status = 200, description = "agent name -> open config PR, only agents with one present", body = std::collections::HashMap), (status = 503, description = "no forge is configured on this host", body = String), ), tag = "agents" )] -async fn get_agent_config_prs( +async fn get_config_prs( State(state): State, ) -> Result>, StatusUnavailable> { let Some(cache) = state.config_prs.as_ref() else { @@ -1034,7 +1042,7 @@ async fn main() -> Result<()> { .routes(routes!(get_jobq_graph)) .routes(routes!(get_jobq_rollup)) .routes(routes!(get_agent_config_pr)) - .routes(routes!(get_agent_config_prs)) + .routes(routes!(get_config_prs)) .routes(routes!(create_agent)) .routes(routes!(webhook::post_webhook_forge)) .split_for_parts();