feat: scope server pins by port, default port inherits (agreed with bunshin)

This commit is contained in:
randogoth 2026-09-30 13:46:05 +03:00
parent 96a558da16
commit 13c624f2b0
7 changed files with 149 additions and 48 deletions

View file

@ -170,8 +170,9 @@ fn main() {
/// reports the distinction; only the CLI knows the command.
fn hint(error: Option<&fumi::error::Error>) {
match error {
Some(fumi::error::Error::NotPinned { host }) => eprintln!(
"obtain the key from the operator through a trusted channel, then:\n fumi trust {host} <key>"
Some(fumi::error::Error::NotPinned { host, port }) => eprintln!(
"obtain the key from the operator through a trusted channel, then:\n fumi trust {} <key>",
fumi::address::trust_label(host, *port)
),
Some(fumi::error::Error::KeyChanged { address, offered, .. }) => {
if let Ok(addr) = Address::parse(address) {
@ -358,21 +359,30 @@ fn trust(store: &Store, host: &str, key_b32: &str, force: bool) -> Result<()> {
v.len()
))
})?;
// A pin is per server, and the reference client strips any :port the
// same way its address grammar does: at the first colon.
let host = host.split(':').next().unwrap_or(host);
match store.server_pin(host)? {
// A pin is scoped per server and port (address::trust_label): the port
// splits from the right so a bare host means the default port, and an
// explicit default port normalizes onto the same bare row existing
// stores already hold.
let (host, port) = match host.rsplit_once(':') {
Some((h, p)) => match p.parse::<u16>() {
Ok(port) => (h, port),
Err(_) => (host, fumi::address::DEFAULT_PORT),
},
None => (host, fumi::address::DEFAULT_PORT),
};
match store.server_pin(host, port)? {
Some(old) if old != key && !force => {
return Err(anyhow!(format!(
"{host} is already pinned to {}; use --force to replace",
"{} is already pinned to {}; use --force to replace",
fumi::address::trust_label(host, port),
b32(&old)
))
.into());
}
_ => {}
}
store.pin_server(host, &key)?;
println!("pinned {host} {}", b32(&key));
store.pin_server(host, port, &key)?;
println!("pinned {} {}", fumi::address::trust_label(host, port), b32(&key));
Ok(())
}