{"record":{"id":"6999d7555240f3ee","repo":"zeroclaw-labs/zeroclaw","slug":"uno-q-host-must-contain-at-most-one","errorCode":null,"errorMessage":"Uno Q host must contain at most one '@'","messagePattern":"Uno Q host must contain at most one '@'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-hardware/src/peripherals/uno_q_setup.rs","lineNumber":87,"sourceCode":"        .status()\n        .context(\"arduino-app-cli start failed\")?;\n    if !status.success() {\n        anyhow::bail!(\"Failed to start Bridge app. Ensure arduino-app-cli is installed on Uno Q.\");\n    }\n\n    println!(\"ZeroClaw Bridge app started. Add to config.toml:\");\n    println!(\"  [[peripherals.boards]]\");\n    println!(\"  board = \\\"arduino-uno-q\\\"\");\n    println!(\"  transport = \\\"bridge\\\"\");\n    Ok(())\n}\n\nfn validated_ssh_target(value: &str) -> Result<String> {\n    let mut parts = value.split('@');\n    let first = parts.next().unwrap_or_default();\n    let second = parts.next();\n    if parts.next().is_some() {\n        anyhow::bail!(\"Uno Q host must contain at most one '@'\");\n    }\n\n    let (user, host) = match second {\n        Some(host) => (first, host),\n        None => (\"arduino\", first),\n    };\n\n    if !valid_ssh_user(user) {\n        anyhow::bail!(\n            \"Invalid Uno Q SSH user: use only ASCII letters, digits, '.', '_', or '-' and do not begin with '-'\"\n        );\n    }\n    if !valid_ssh_host(host) {\n        anyhow::bail!(\n            \"Invalid Uno Q host: use a DNS hostname or IPv4 address without SSH/SCP syntax characters\"\n        );\n    }\n","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-hardware/src/peripherals/uno_q_setup.rs#L69-L105","documentation":"validated_ssh_target splits the value on '@' and requires at most one separator, so 'user@host' or bare 'host' (user defaults to 'arduino') are the only accepted shapes. This bail fires on values with two or more '@' characters — 'user@@host', 'a@b@c' — because they are ambiguous between user and host and cannot be safely passed to ssh/scp.","triggerScenarios":"Passing a host string like 'team@deploy@uno-q.local' or a typo'd 'arduino@@192.168.0.48' to setup_uno_q_bridge(Some(host)).","commonSituations":"Copy-pasted targets that already include a destination or doubled separator; templated config values injecting an extra '@'; attempts to smuggle extra ssh syntax through the host field.","solutions":["Use the single supported shape: 'host' or 'user@host', e.g. 'operator@uno-q.local'","Strip accidental double '@' characters and re-check the value before passing it"],"exampleFix":"# before\nsetup_uno_q_bridge(Some(\"arduino@@192.168.0.48\"))\n\n# after\nsetup_uno_q_bridge(Some(\"arduino@192.168.0.48\"))","handlingStrategy":"type-guard","validationCode":"if !is_valid_ssh_target_shape(host) {\n    anyhow::bail!(\"expected 'host' or 'user@host', got {host:?}\");\n}\nsetup_uno_q_bridge(Some(host))?;","typeGuard":"fn is_valid_ssh_target_shape(value: &str) -> bool {\n    !value.is_empty() && value.matches('@').count() <= 1\n}","tryCatchPattern":null,"preventionTips":["Build host strings from validated components (user + host) instead of pasting","Run targets through the shape check in config validation, before deploy time"],"tags":["input-validation","ssh-target","uno-q"],"backgroundTag":"invalid-ssh-target","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}