Split the command line by level

`up` now says which level each setting belongs to, and `--help` shows the
two sections. System: how the agent reaches peers, the one interface it
owns, the address range, the resolver. Transport: which protocols carry
packets and what they take.

`--wireguard` is gone. `--protocol` takes a list and defaults to
`wg-quic`, which is what the protocol is now called — WireGuard's
cryptography in QUIC datagrams, so the name says what is on the wire
rather than what the implementation borrows. `--protocol none` runs the
control plane alone.

Protocol settings moved to `-o key=value`, or `-o protocol:key=value`
when several are selected. Each protocol declares its own settings and
their help, so `tsunagi protocols` can list them without the agent
knowing anything about any protocol, and a setting nobody takes is
refused rather than dropped — a dropped setting looks exactly like one
that did not work. What the user asked for is checked before anything
that could fail on its own, so a misspelled protocol is not buried under
a privilege error.

`--wg-prefix` and `--wg-mtu` became `--interface` and `--mtu`: they were
never the protocol's, and the interface they describe belongs to the
agent. `--transport` became `--reach`, because "transport" now means the
protocol level and using the word for iroh's path policy as well would
be a collision of meaning rather than a shortage of words.

The plugin gave up the last things that were not its own: the interface
name it carried in its own state, and the check that this agent's
address is really on an interface. Both are the agent's, and the check
is now the agent's too, still said once per address rather than every
round.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
tsunagi
2026-09-21 19:44:21 +01:00
co-authored by Claude Opus 5
parent 7c1be332e3
commit ff7e235414
6 changed files with 386 additions and 154 deletions
+3 -4
View File
@@ -474,10 +474,10 @@ async fn an_allocated_address_missing_from_the_host_is_reported() {
reason.contains(&allocated.to_string()),
"unexpected: {reason}"
);
// The agent assigns the address itself, so the report says which
// interface should have had it rather than a command to run.
// The agent owns the interface, so it is the agent that notices and the
// report names the interface the address should have been on.
assert!(
reason.contains(&a.plugin.overview(network_id).unwrap().interface),
reason.contains(&a.agent.overlay().unwrap().interface),
"must name the interface: {reason}"
);
@@ -815,7 +815,6 @@ async fn restarting_keeps_the_wireguard_identity_and_overlay_address() {
})
.await;
assert_eq!(after.public_key, before.public_key);
assert_eq!(after.interface, before.interface);
// The tunnel comes back on its own.
wait_until("the tunnel is re-established", || async {