Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
2.8 kB
P11 slice 221 — 760 RPL_WHOISKEYVALUE (metadata in WHOIS)#
Goal#
Close a documented IRCv3 draft/metadata-2 deferral: a WHOIS on a user with metadata
set now exposes that metadata as 760 RPL_WHOISKEYVALUE lines, to a requester that
negotiated the draft/metadata-2 capability. Format (the metadata spec, §RPL_WHOISKEYVALUE):
:<server> 760 <requester> <target> <key> <visibility> :<value>
This was listed verbatim as out-of-scope in command/metadata.rs ("760 RPL_WHOISKEYVALUE … out of scope here"). leveva-native (no C oracle — IRCnet 2.11 has no
metadata); modelled on the draft/metadata-2 spec and the existing 761 RPL_KEYVALUE
(METADATA … GET) which shares the identical param shape.
Scope / behavior#
- Gated on the requester's cap (
client.caps.metadata), per the spec ("when a user with the capability enabled runs WHOIS"). A requester without the cap sees no760(the inverse). - One
760per set key, in the deterministicMetadataStore::list(sorted) key order. - Visibility is always
*— leveva has no privileged-key / restricted-visibility system (that whole subsystem stays out of scope; the only remaining metadata-2 deferral). - Fires for remote targets too: metadata is keyed by stable
Uidand is network-wide (burst slice 189 + live propagate slice 177), so a remote user's keys are in our store. - Placed among the WHOIS extra-info lines, before the 317/318 tail (after 276/379).
Mechanism#
numeric.rs: addRplWhoiskeyvalue = 760(name map +try_from).command/whois.rs: pure builderwhois_keyvalue_lines(ctx, requester, target, &[(k,v)]) -> Vec<Message>— one760line per pair, visibility*, value as trailing. The fuzz seam.command/whois.rshandler: in the per-target block,if client.caps.metadatafetchctx.registry.metadata().list(&MetaTarget::User(rec.uid))andreplies.extend(...)the builder output, just before the 317 idle line.
Tests (TDD)#
whois.rsunit: cap-enabled WHOIS shows760for each key (sorted,*visibility, before 317); inverses — no cap → no760; cap but no keys → no760; set→remove round-trip drops the760; a remote target still gets760. Pure-builder shape + empty.whois.rsinline proptest: the builder is total over arbitrary keys/values, one760per pair, params<req> <tgt> <key> *+ value trailing.tests/golden_whois_metadata.rs(boot-golden): alice sets two keys; a cap-enabledbobWHOIS sees both760lines sorted before 318; a non-capcarolsees none (the inverse), end-to-end through the real binary.
Gate#
cargo test -p leveva green; cargo clippy -p leveva --tests clean; cargo build --workspace 0 warnings.