refactor: extract leveva-cloak leaf crate (+ proptest fuzzing)
Continue the leaf-crate carve-out (after leveva-casemap / leveva-string /
leveva-message / leveva-patricia / leveva-cidr) by moving the +x hidden-host
transform out of the monolith into its own workspace crate:
- leveva-cloak: the deterministic FNV-keyed IP/host cloak (cloak / cloak_ip /
cloak_host), a faithful port of Elemental-IRCd's ip_cloaking.c. The cleanest
remaining leaf, exactly as the leveva-cidr survey predicted ("zero intra-crate
deps — perfect standalone leaf, strongest next pick"): it depends only on
std::net::IpAddr and on nothing in the workspace. Its only crate::-references
were doc comments — the actual code edges all run *into* it
(command::mode::apply_cloak_change at mode.rs:916 and session.rs:1786 call
crate::cloak::cloak), so no cycle.
leveva re-exports it as leveva::cloak (`pub use leveva_cloak as cloak;`), so every
crate::cloak::* / leveva::cloak::* path is unchanged across consumers. Body moved
verbatim via git mv — no doctest, and every intra-doc link (cloak/cloak_ip/
cloak_host/IP_CHARTABLE/HOST_ALPHABET + the FNV reference) resolves in-module, so
nothing repointed.
Fuzzing: stable toolchain only (no nightly / no cargo-fuzz), so proptest is the
runnable fuzz tier, matching casemap/string/cidr. And since the C 2.11 oracle has
no +x usermode, there is NO differential oracle here — the 10 proptest invariants
ARE the gate, not a supplement. Fed arbitrary (incl. non-ASCII) strings and the
full v4/v6 address space: determinism (the ban-on-a-cloak-keeps-biting contract),
the leading-colon wire-safety biconditional (a non-: input never grows a leading
colon, a :-input is returned verbatim), length preservation for both cloak_ip and
cloak_host, separator/dot byte-index invariance, IP-literal dispatch to cloak_ip,
the g-z IP alphabet (v4 keeps its first two octets; v6 is hex/:/g-z with no leading
colon), and fnv_hash_32 == charybdis's explicit shift-decomposition over arbitrary
bytes.
What else can move out: matching (now a clean casemap+cidr leaf, pulls nom — the C
match.c cluster, natural next pick); uid (only crate::ident, blocked on extracting
ident); msgid pulls cap/clock/ident. Recorded in the plan + progress log.
Gate: cargo build --workspace 0 warnings; cargo clippy --workspace --tests clean;
leveva-cloak 18 (8 unit + 10 fuzz) green; leveva +x consumer tests (command::mode
plus_x suite + session registers-cloaked + the s2s +s+x spy, 8) green.