feat(#2302): parse agent names into AgentName newtype at dashboard boundary

This commit is contained in:
damocles 2026-07-19 17:46:04 +02:00 committed by mara
commit cfac917b4d
8 changed files with 162 additions and 103 deletions

View file

@ -425,7 +425,7 @@ async fn handle_get_agent_meta(
// the OS level. Validate it before any path is built. The `None` default
// (`target == agent`) is the caller's own authenticated name, already
// valid — but validating unconditionally is simplest and harmless.
if let Some(reason) = crate::dashboard::validate_agent_name(target) {
if let Err(reason) = crate::dashboard::AgentName::parse(target) {
return hive_agent_sock::Response::Err {
message: format!("get_agent_meta: invalid agent name {target:?}: {reason}"),
};
@ -445,7 +445,7 @@ async fn handle_get_agent_meta(
// `@user:server` / `homeserver`) — the access token lives separately
// in the agent's `matrix-token` and is never part of this response.
// Peer visibility is intentional: it lets an agent verify/contact
// another on a public matrix instance. The `validate_agent_name` gate
// another on a public matrix instance. The `AgentName::parse` gate
// above is what closes the real vector here (path traversal via `../`
// in an agent-supplied name).
matrix_accounts: read_agent_matrix_identities(target),
@ -748,7 +748,7 @@ fn require_group(agent: &str, group: &str, action: &str) -> Option<Response> {
/// `submit_init_config`, which builds filesystem paths from it, so validate
/// before that.
fn require_new_child(agent: &str, target: &str, action: &str) -> Option<Response> {
if let Some(reason) = crate::dashboard::validate_agent_name(target) {
if let Err(reason) = crate::dashboard::AgentName::parse(target) {
return Some(Response::Err {
message: format!("agent `{agent}` cannot {action} `{target}`: {reason}"),
});