---
name: leveva-ircv3-track
description: leveva has an IRCv3 track starting at P11 slice 48 (CAP negotiation framework); how to add a capability and the framework-vs-behavior scope rule
metadata: 
  node_type: memory
  type: project
  originSessionId: dc315cf7-0867-45e4-98a1-f2a021b6ea94
---

P11 slice 48 (2026-06-09) opened an **IRCv3 track** in leveva, starting with the `CAP`
capability-negotiation **framework** in `leveva/src/cap.rs` (`CapState` per-connection +
the static `SUPPORTED` registry; `Session` owns one `CapState` and CAP suspends/resumes
registration via a two-gate finalize — auth verdict AND `CAP END`). The C 2.11 oracle has
no CAP, so this and every IRCv3 slice is leveva-native: **no `leveva-integration`
differential** — the gate is unit + boot-golden + proptest only (like [[leveva-next-step-s2s-completeness]] slices 45–47).

**Hard scope rule (locked with the user):** the negotiation *mechanism* and the *behavior*
of each capability are **separate slices**. Slice 48 shipped the framework + `cap-notify`
ONLY (the one cap the framework itself honors). Behavior-bearing caps — multi-prefix,
userhost-in-names, message-tags, server-time, etc. — each get their own later slice and are
added to the `SUPPORTED` table in `cap.rs`. Don't fold a behavior cap into a framework change.

**Slice 51 (2026-06-10) shipped `multi-prefix`** — the FIRST behavior-bearing cap. The
reusable pattern for the next behavior cap: add the name const + a `SUPPORTED` entry; add a
field to `cap::ClientCaps` (the per-conn snapshot struct) + `CapState::client_caps()`;
`command::Registered.caps: ClientCaps` holds the snapshot (set at finalize, **re-synced**
after `cap.apply` in `session.rs` so a post-registration `CAP REQ` is honored live); the
affected handlers read `client.caps.<field>`. multi-prefix's effect is
`MemberStatus::prefixes(multi)` in `channel.rs`, threaded through `names_reply` / WHO
`who_status` / `whois_channels` (gates NAMES 353 / WHO 352+WHOX 354 / WHOIS 319). Adding a
cap to `SUPPORTED` changes the LS token list → expect the `golden_cap` snapshots +
`supported_names` test to update (deliberate). NOTE the churn: `Registered` is built as a
struct literal in ~25 test sites — a new field touches all of them (use a `Default` field).

**Slice 53 (2026-06-10) shipped WebSocket transport** (IRCv3 `websocket`) — the first
**transport** slice (all prior spoke raw TCP/TLS). Served by **axum** (`axum`+`hyper-util`
deps; tokio-tungstenite owns the WS protocol) at HTTP path `/socket`. Structure: pure
IRC-over-WS helpers in `leveva::websocket` (`websocket/mod.rs` — `negotiate`/`decode_incoming`/
`frame_lines`/`origin_allowed`/`proxy_trusted`, faithful to InspIRCd `m_websocket.cpp`,
fully proptested) + the axum glue in `leveva::websocket::server` (`websocket/server.rs` —
`serve_websocket`/`ws_handler`/`serve_ws`). **`tls.rs` was promoted from a binary module to
`leveva::tls`** so the ws server is a clean lib submodule (it needs `TlsEndpoint`). A
`listen{}` port becomes a ws port via a nested `websocket{}` block (`origins`/`proxy-ranges`/
`default-mode`); `Listener.websocket: Option<WebsocketConfig>` + `DefaultMode` in config; the
binary's accept loop branches on it. `serve_ws` reuses the **same `Session` state machine**
(a dedicated `select!`, one ws frame per outbound line via `SinkExt::send`). **New
leveva-native `UserMode::Websocket` (`+W`, `0x0040`)**: set at registration for ws sessions
(`Session::set_websocket`), shown in WHOIS as `320`; **propagates network-wide** (in
`SEND_UMODES` = 125, carried by `UNICK` — the user's explicit call, so remote ws users' WHOIS
shows 320 too) but **server-set-only** (client `+W` silently ignored). It joins the advertised
umode list → `RPL_MYINFO`/ISUPPORT are now `oOiwraW` (snapshots updated). Config flag lives in
a `listen` (NOT `connect`) block. End-to-end gate: a real `tokio-tungstenite` client in
`tests/golden_websocket.rs`. leveva-native (no differential). Also added the table-formatted
`HELP USER_MODES`/`CHANNEL_MODES` topic pages (see [[help-files-per-command]]). Plan:
`docs/superpowers/plans/2026-06-10-p11-slice53-websocket.md`.

**Slice 55 (2026-06-10) shipped IRCv3 bot mode** — a *client-settable* `+B` umode
(`UserMode::Bot`, bit `0x0080`, leveva-native). The reusable pattern for a
client-settable leveva-native umode (contrast `+W`'s server-set-only): add the
variant to `mode.rs` (`ALL`/`as_char`/`bit`/`from_char`/`from_bit`/`render`/`Display`,
appended last so oracle bits are untouched); add the letter to the **settable** arm
`'i' | 'w'` in `command::mode::umode()` AND to `umode_diff`'s iterated list (so the
echo carries it); add the bit to `s2s::umode::SEND_UMODES` to propagate. Surfaced via
`BOT=B` ISUPPORT (`isupport.rs` — also bumps `user_modes_string()` to `oOiwraWB`, so
the 4 `004`/`005` golden snapshots regenerate), `335 RPL_WHOISBOT` in `whois.rs` (after
the `320` slot), and the `B` WHO/WHOX flag in `who::who_status` (after `H`/`G` and the
oper `*`). **The `bot` MESSAGE TAG is DEFERRED** to the future `message-tags` slice (user
ruling): the `Message` type has no tag rendering yet and the tag only reaches
`message-tags` subscribers, so it's dormant regardless. Tests: dedicated
`bot_mode_proptest.rs` (lockstep `{i,w,B}` model + observer WHO/WHOIS) + `golden_bot_mode.rs`.
Plan: `docs/superpowers/plans/2026-06-10-p11-slice55-bot-mode.md`.

**Slice 56 (2026-06-10) shipped the `message-tags` FOUNDATION** — the highest-leverage
IRCv3 slice, because the `Message` type had **no** tag support, the hard prerequisite
blocking ≥5 spec'd caps (the slice-55 bot tag, server-time, message-ids, message-redaction,
oper-tag). Split framework-vs-behavior per the rule above: **56 = the machinery**, **57 =
the delivery behavior**. Slice 56: `Message`/`MessageBuilder` carry ordered
`tags: Vec<(String,String)>`; `parse` peels a leading `@key=value;...` segment (length-checked
vs `MAX_TAG_DATA_LEN=8191` → `ParseError::TagsTooLong`, values unescaped via the spec table);
`write_into` split into `write_tags_into`+`write_body_into` so `to_wire` caps **only the body**
at 512 and the tag prefix is separate budget; accessors `tags()`/`tag(key)`; builder `.tag(k,v)`.
Escaping both ways: `;`↔`\:`, ` `↔`\s`, `\`↔`\\`, CR↔`\r`, LF↔`\n`. Advertised `message-tags`
in `cap.rs` SUPPORTED + `ClientCaps.message_tags`. **Behavior-bearing on its own**: once
advertised, tag-capable clients send `@tag PRIVMSG …` and the server now parses the `@tags`
segment correctly (else `@tags` is mistaken for the command); a client-only `+`tag is parsed
and currently **dropped** (not relayed). **Normalization:** `key` and `key=` both → `(key,"")`
→ render bare `key` (so render→parse→render is a fixed point). Tests: message.rs units +
`message_tags_proptest.rs` (round-trip/escaping/never-panic/untagged-no-regression) + the 2
`golden_cap` snapshots regenerated. **Slice 57 (NEXT, deferred) = the behavior:** the `TAGMSG`
command, client-only (`+`) tag relay to `message-tags` subscribers (per-recipient cap gating
in the delivery plane — `command/message.rs` currently sends ONE wire to all members, so this
needs a tagged/untagged split keyed on each recipient's `ClientCaps.message_tags` — AND across
S2S `relay.rs`), and `417 ERR_INPUTTOOLONG` on oversized inbound tag data. Plan:
`docs/superpowers/plans/2026-06-10-p11-slice56-message-tags.md`. Once it lands, attaching a tag
is just `Message::builder(..).tag("time", ts)` — server-time/msgid/bot-tag/oper-tag become thin
follow-ons.

**Slice 58 (2026-06-10) shipped the message-tags DELIVERY PLANE** — the behavior slice 56
deferred (it landed as **58**, not 57; slice 57 took the PRIVMSG mask-targets path instead).
Three pieces: (1) `TAGMSG <target>` (new `command/tagmsg.rs` + dispatch arm + `s2s::relay::
inbound_tagmsg`/`local_tagmsg`/`route_tagmsg_to_remote`), delivered **only** to `message-tags`
consumers (a non-consumer gets nothing; for a nick target not an error); errors mirror PRIVMSG
(411/404/401, no 412); (2) per-recipient **client-only (`+`) tag relay** on PRIVMSG/NOTICE/
TAGMSG — `Message::client_only_tags()` (new) filters the `+`-prefixed subset; the fan-out
builds a tagged variant for cap-havers and the plain wire for everyone else; unprefixed server
tags stripped; carried across S2S unconditionally (`local_channel_message`/`route_message_to_
remote` gained a `tags` param). The gate is a **`ClientRecord.caps: ClientCaps` snapshot**
mirrored from the connection via new `Registry::set_caps`/`caps_of` (at registration + post-reg
`CAP`), exactly as `set_modes` mirrors `+i`; (3) `417 ErrInputtoolong` (new numeric) in
`session.rs::feed` on `ParseError::TagsTooLong` (no longer a silent drop; pre-reg target `*`).
Divergences: mask broadcasts don't carry client tags; a `$$`/`$#` TAGMSG target isn't a mask
(→401); no `CLIENTTAGDENY`. Help: `help/TAGMSG.md` + index. Tests: units across message/tagmsg/
registry/session/relay + `golden_tagmsg.rs` + `tagmsg_proptest.rs` (the full assembled CAP→reg→
delivery gate). See [[leveva-message-tags-seams]]. Plan: `docs/superpowers/plans/2026-06-10-
p11-slice58-tagmsg-client-tags-417.md`. Now attaching a tag is just `.tag("time", ts)` →
server-time/msgid/bot-tag/oper-tag are thin follow-ons.

**Behavior caps on the slice-58 cap mirror (59–61, 2026-06-10):** once the
`Registry::set_caps`/`caps_of` + `Registered.caps` snapshot existed, each subsequent
behavior cap is a thin per-recipient/per-sender gate read off it — no new plumbing. **59
`away-notify`** (`:nick AWAY [:msg]` to a channel co-member's negotiating clients on an away
*change* or away-user JOIN; gate `caps_of(recipient).away_notify`). **60 `invite-notify`**
(`:inviter INVITE <target> :<chan>` to channel **ops** that negotiated it on a successful
INVITE; `command/invite.rs::notify_channel_ops`). **61 `echo-message`** (sender gets a copy
of its own PRIVMSG/NOTICE/TAGMSG per successful target; `command/message.rs` + `tagmsg.rs`
`echo_to_sender` closure reusing the slice-58 `pick` so the echo carries `+` tags iff the
sender consumes message-tags; gate is **`client.caps.echo_message` straight off the
`Registered`** — no `caps_of` round-trip, the sender is the local connection). Common
divergence shared by 59/60: **remote** members aren't notified (single-server local-mailbox
relay). echo-message was deliberately chosen over `server-time` for slice 61 to keep golden
snapshots wall-clock-deterministic. Plans: `…slice59-away-notify.md`/`…slice60-invite-notify.md`/`…slice61-echo-message.md`.

**Slice 62 (2026-06-10) shipped `server-time`** — the server stamps an
`@time=YYYY-MM-DDThh:mm:ss.sssZ` (RFC 3339 millis, UTC) tag on each delivered/echoed
`PRIVMSG`/`NOTICE`/`TAGMSG` for a negotiating recipient. Reusable patterns established: (1)
the per-target `pick(bool)` in `command/message.rs`/`tagmsg.rs` became `render(ClientCaps)` —
choose the plain-vs-`+`tagged base by `caps.message_tags`, then `Message::with_server_time(&now)`
iff `caps.server_time` (the helper prepends a `("time",ts)` tag at the FRONT so it renders
before client `+`tags); fan-out renders with `caps_of(recipient)`, the slice-61 echo with the
sender's own `client.caps`. (2) **No `ServerContext` clock field** — that would break ~40
`ServerContext {…}` test literals; instead the timestamp is a pure free fn
`clock::format_rfc3339_millis(u64)` (Howard-Hinnant civil_from_days; total/panic-free;
fixed-width + lexicographically monotonic since the year is always 4 digits → the prime
fuzz/proptest target) and golden determinism comes from a **canonicalizer `time=<TS>` mask**
(the established RPL_CREATED/333/391 pattern) + presence/shape (not pinned-value) assertions in
unit/proptest. Scope = the message delivery plane ONLY (the slices-56/58/61 surface); JOIN/PART/
QUIT/MODE/TOPIC/etc., numeric replies, mask broadcasts, and **remote** members are deliberate
follow-ons (each thin now `with_server_time` exists). `SERVER_TIME` appended to `SUPPORTED` +
`ClientCaps.server_time` (so the six LS-string asserts + `supported_names` + 2 `golden_cap`
snapshots regenerate). **`server-time` was deferred from slice 61 for snapshot determinism —
now solved by the canonicalizer mask, so future wall-clock-volatile caps golden-test the same
way.** Plan: `docs/superpowers/plans/2026-06-10-p11-slice62-server-time.md`.

**Slice 63 (2026-06-10) shipped `userhost-in-names`** — a new cap (`UHNAMES` in `SUPPORTED` +
`ClientCaps.userhost_in_names`) that renders every `353 RPL_NAMREPLY` member as
`nick!user@host` instead of the bare nick, gated by the **requester's own** cap (read off
`client.caps`, no `caps_of`). One renderer change: `command/mod.rs::names_reply` gained a
`userhost_in_names: bool` param, resolves each member via `Registry::record_of` (nick+user+host)
and composes with `multi-prefix` sigils (`@+nick!user@host`); the 3 call sites (NAMES named/sweep
+ JOIN burst) thread `client.caps.userhost_in_names`. The legacy `PROTOCTL UHNAMES`/ISUPPORT
method is deliberately NOT implemented (CAP-only, per the RFC). Plan:
`…slice63-userhost-in-names.md`.

**Slice 64 (2026-06-10) shipped the `bot` MESSAGE TAG** — lit up slice 55's deferred bot tag,
the thin follow-on mirroring slice 62. **Key contrast with 59–63: NO new capability.** The bot
tag isn't negotiated by the receiver — it's gated by the **existing** `message-tags` cap AND the
**sender's** `+B` mode (`sender_is_bot = client.modes & UserMode::Bot.bit() != 0`), so
`cap.rs`/`ClientCaps`/`SUPPORTED` are untouched. New `Message::with_bot_tag()` inserts a valueless
`("bot","")` at the FRONT (like `with_server_time`; both → `@time;bot;+client`). The
`render(caps)` closures in `command/message.rs`/`tagmsg.rs` became a 2×2 match over
`(bot, server_time)` where `bot = sender_is_bot && caps.message_tags`; the echo carries `@bot` iff
the bot sender itself consumes message-tags. Scope = PRIVMSG/NOTICE/TAGMSG delivery plane only
(other commands + numerics + remote members are follow-ons — a remote's own server stamps the tag
from network-propagated `+B`). Gate: units + `golden_bot_tag.rs` + `bot_tag_proptest.rs` (the
valueless tag is deterministic → no canonicalizer rule). Plan: `…slice64-bot-tag.md`.

**Slice 66 (2026-06-10) shipped `message-ids` (the `msgid` tag)** — the next thin follow-on
after 62/64. **NO new capability** (rides `message-tags`, like the slice-64 bot tag, so
`cap.rs`/`ClientCaps`/`SUPPORTED` untouched). New `leveva::msgid` module:
`generate(sid)`=`<sid>-<hex AtomicU64 counter>` (monotonic→unique, sid prefix→cross-server
unique) + `is_valid(s)` (spec byte rule: non-empty, no leading `:`, no SPACE/CR/LF). New
`Message::with_msgid(id)` prepends `("msgid",id)` between `with_bot_tag` and `with_server_time`
→ wire order `@time;msgid;bot;+client`. The `render(caps)` closures in `command/message.rs`/
`tagmsg.rs` went from a 2×2 `(bot,server_time)` match to a small composition (fast path +
conditional `with_bot_tag`/`with_msgid`/`with_server_time`). **Per-event invariant:** one id per
target, minted lazily into a per-target `std::cell::OnceCell<String>` so every channel member +
the echo of one message share the SAME id; distinct messages differ. Gated on `message-tags`
(spec) → a server-time-only consumer gets `@time` but no `msgid` (verified: server-time/echo/
privmsg goldens unchanged). Canonicalizer gained a `msgid=<MSGID>` mask (counter-derived →
volatile, like `time=<TS>`); `golden_bot_tag`/`golden_tagmsg` snaps regenerated to `@msgid=…;bot`
/`@msgid=…;+example=…`. Divergences: single-server-local (S2S relay unchanged, remote stamps its
own); in-memory counter resets on restart (spec calls this out, accepted). Gate: `msgid.rs`/
message/tagmsg units + `golden_msgid.rs` + `msgid_proptest.rs` (400 cases: gated-iff-cap,
always-valid, per-event sharing + distinctness, panic-freedom). Plan: `…slice66-msgid.md`.

**Slice 67 (2026-06-10) shipped `oper-tag` (the `draft/oper` tag)** — the next IRCv3 cap after 66.
**HAS its own capability `draft/oper-tag`** (unlike the bot/msgid tags that ride `message-tags`),
so `cap.rs`/`ClientCaps.oper_tag`/`SUPPORTED` DO gain an entry (the 8 LS-string asserts +
`supported_names` + 2 `golden_cap` snaps regenerate, appending ` draft/oper-tag`). Mechanism =
the slice-64 bot-tag analog with two swaps: gate bit is `+o`/`+O` (`sender_is_oper`, hoisted next
to `sender_is_bot`, reused for the existing `$$`/`$#` mask check) not `+B`, and the recipient gate
is `draft/oper-tag`'s OWN cap (independent of `message-tags`, per spec — negotiating the cap
declares the client parses tags). New `Message::with_oper_tag()` prepends a **valueless**
`("draft/oper","")` (`draft/` prefix MANDATORY until the WIP spec ratifies — both cap name
`draft/oper-tag` and tag name `draft/oper`); applied after `with_msgid`, before `with_server_time`
→ wire `@time;draft/oper;msgid;bot;+client`. The `render(caps)` closures in
`command/message.rs`/`tagmsg.rs` add `oper_tagged = sender_is_oper && caps.oper_tag` to the no-tag
fast-path guard + a `with_oper_tag()` arm. **Divergence: VALUELESS tag** (spec permits valued
`draft/oper=<account>` but leveva keeps no post-OPER account store — only the mode bit + privilege
set; valueless conveys the security-relevant fact, the spec's own example line 2). Scope =
PRIVMSG/NOTICE/TAGMSG delivery plane only; single-server-local (S2S unchanged); no mask-broadcast
tagging. Gate: cap/message/tagmsg units + `golden_oper_tag.rs` (alice `OPER root hunter2` then
speaks; dan w/ `draft/oper-tag` sees `@draft/oper`, mel bare) + `oper_tag_proptest.rs` (400 cases,
full 2×2 truth table sender-oper×recipient-cap + toggle-flips-tag inverse + panic-freedom). Plan:
`…slice67-oper-tag.md`. **Pitfall: a blanket `perl -pe` over `userhost-in-names\r\n` also hits the
`CAP REQ :userhost-in-names` ACK assertions — patch the LS line only.**

**Slice 68 (2026-06-10) shipped `message-redaction` (the `REDACT` command + `draft/message-redaction`
cap)** — the next IRCv3 cap after 67, and **TWO firsts on the track: the first NEW COMMAND
(`REDACT`) and the first standard-replies `FAIL` line.** Cap added to `cap.rs`/`SUPPORTED`/
`ClientCaps.message_redaction` (LS-string asserts + `supported_names` + 2 `golden_cap` snaps
regenerate, appending ` draft/message-redaction`). New `command/redact.rs` +
`mod redact;`/dispatch arm `"REDACT"`: `REDACT <target> <msgid> [<reason>]` routes like a PRIVMSG
to a **single** target (no comma list, per the spec's singular `<target>`) and forwards
`:sender!u@h REDACT <target> <msgid> [:reason]` only to recipients with `message_redaction`
(others get NOTHING, spec MUST NOT). **Key design = STATELESS RELAY:** leveva keeps no message
history (msgids are an in-memory counter, slice 66), so it does NO authorship/permission/
msgid-existence validation and NEVER emits `UNKNOWN_MSGID`/`REDACT_FORBIDDEN`/
`REDACT_WINDOW_EXPIRED` — the spec's explicit relay model. The one reachable error is the spec's
`FAIL REDACT INVALID_TARGET <target> :You cannot delete messages from <target>` (leveva's FIRST
`FAIL`; the full standard-replies framework — the `standard-replies` cap, WARN/NOTE — is a later
independent-track slice). Reason read from `msg.trailing()` OR `params()[2]` (single-word reason
can be a plain middle param), always re-emitted as trailing. Divergences: sender cap NOT enforced
(any registered client may send REDACT; gate is recipient-only — the TAGMSG precedent);
single-server-local (S2S relay of REDACT deferred); no server tags on the REDACT line;
`message-tags` dependency not enforced (caps ACKed independently). Gate: cap unit + 10 redact
units (incl. inverses: non-cap co-member/nick gets nothing, sender skipped, moderated/ghost →
FAIL, absent-reason → no trailing) + `golden_redact.rs` (bob w/ cap sees REDACT, mel plain sees
none — sentinel-PRIVMSG technique) + `redact_proptest.rs` (400 cases: delivered-iff-cap,
reason-preserved, toggle-flips-delivery, panic-freedom). Plan:
`…slice68-message-redaction.md`. **Pitfall: `Message::params()` EXCLUDES the trailing param —
assert the reason via `m.trailing()`, not `params()[2]`.**

**Slice 69 (2026-06-10) shipped `standard-replies` (the `FAIL`/`WARN`/`NOTE` framework + cap)** —
a **framework slice** (the framework-vs-behavior split, like slice 48/56): it formalized the
slice-68 ad-hoc redact `FAIL` into a shared builder + advertised the cap. New `leveva::stdreply`
module: `ReplyType{Fail,Warn,Note}` (`verb()`) + `standard_reply(server, ty, command, code,
context: &[&str], description) -> Message` + `fail`/`warn`/`note` wrappers (format `<TYPE>
<command> <code> [<context>...] :<description>`; prefix=server, description always trailing).
`cap.rs` gained `STANDARD_REPLIES="standard-replies"` + SUPPORTED (appended LAST) +
`ClientCaps.standard_replies` + client_caps line (→ the 8 LS-string asserts + `supported_names` +
2 `golden_cap` snaps regenerate, appending ` standard-replies`; the slice-68 message_redaction
"advertised last" assert relaxed to containment). `command/redact.rs::fail_invalid_target`
refactored onto `stdreply::fail` — **byte-identical**, so slice-68 redact units/golden/proptest
unchanged. **KEY divergence (= teeth deferred, like message-tags slice 56):** the cap is
advertised/negotiable + the builder is live, but `ClientCaps.standard_replies` is **wired but not
yet read** — a `FAIL` enabled by a specific spec (the redact one) is sent regardless of the cap;
the cap governs only ARBITRARY (non-spec-enabled) replies, which leveva doesn't emit yet. No
WARN/NOTE caller yet. Gate: 6 stdreply units + the cap unit + `golden_standard_replies.rs` (negotiate
cap, `REDACT #nope 123`→`FAIL REDACT INVALID_TARGET #nope`) + `stdreply_proptest.rs` (400 cases,
the fuzz target = the new builder: build→to_wire→parse round-trip + empty-context-no-stray-param +
panic-freedom). **Fuzz finding:** a middle param (command/code/context) must NOT start with `:`
(re-parses as the trailing) — constrained the generator's first char (real codes are uppercase
idents). Plan: `…slice69-standard-replies.md`.

**Slice 70 (2026-06-10) shipped `MONITOR`** — the IRCv3 online/offline watch list, and the
track's FIRST **server-pushed-on-a-lifecycle-event** feature (vs gating a reply). **NOT a CAP**
— advertised via the `MONITOR=100` ISUPPORT (005) token, so `cap.rs`/`SUPPORTED` untouched (but
the 005 list hit 14 tokens → `NETWORK` wraps to a 2nd 005 line, `TOKENS_PER_LINE=13`; 5
005-goldens regenerated). New `leveva::monitor` module: `MONITOR_LIMIT=100` + a shared
`Monitors` index (`Mutex<{by_target: folded-nick→HashSet<watcher Uid>, by_watcher:
Uid→Vec<display>}>`) — **watch state keyed by the watcher's UID, NOT on `Registered`** (the key
design choice: avoids the ~25 Registered test-literal sites — the slice-51 churn lesson) — plus
free fns `notify_online`/`notify_offline` (deliver `730 :nick!u@h` / `731 :nick` to each
watcher's mailbox, addressed to the watcher's live nick). New `command/monitor.rs` + dispatch
arm: `+`(add≤limit, report 730/731, overflow→`734`)/`-`/`C`/`L`(732+733)/`S`, comma-chunked
within the 512 budget; no-modifier→461, unknown modifier/invalid-nick→silent skip. Live-notify
hooks at the lifecycle seams: `session.rs::finalize_registration`→online, `session.rs::release`→
offline + `monitors.clear`, `command/nick.rs::nick_change`→offline(old)+online(new) (a rename =
offline-of-old + online-of-new). Numerics 730–734 added. `ServerContext.monitors` field (+ the
43 proptest literals, inserted after `peers:`). Help: `help/MONITOR.md` + COMMANDS + index.
**KEY divergence: single-server-local** — online status (`+`/`S`) reads the registry (which holds
remote S2S users), but live `730`/`731` pushes fire only on LOCAL events; remote transitions over
S2S don't push (the track's single-server stance, slices 59+). Other divergences: CAP-less (no
PROTOCTL/WATCH); 730 always carries the hostmask; re-add is a silent no-op. Gate: monitor module
units (6) + command units (11) + live-notify seam units (session/nick) + `golden_monitor.rs`
(two clients: offline→online→offline) + `monitor_proptest.rs` (3: index-vs-model, chunker
budget/lossless/capped, junk-never-panics). Plan: `…slice70-monitor.md`.

**Slice 71 (2026-06-10) shipped `chghost`** — the operator self-`CHGHOST` command + the cap notify
plane + `ENCAP CHGHOST` S2S relay (the user explicitly directed: "to get chghost working you need
to send encap CHGHOST commands to other links"). `chghost` added to `cap.rs`/`SUPPORTED`/
`ClientCaps.chghost` (LS-string asserts + `supported_names` + 2 `golden_cap` snaps regenerate,
appending ` chghost`). **Origination is SELF-only** (`CHGHOST <newuser> <newhost>` changes the
*issuing* oper's own identity — it owns its `Registered`, so the mutation is in-place and correct;
targeting another user needs a control-envelope leveva lacks, a documented future extension — this
is what resolves the old "needs a vhost path" blocker). Gated on `+o`/`+O` like KILL (**no new
`OperPrivilege`** — that enum is 1:1 with oracle `ACL_*` bits); new `Registry::set_host` mirrors
user+host. **The shared `s2s::chghost::notify_co_members(ctx,uid,nick,old_user,old_host,newuser,
newhost)` does the spec's TWO delivery modes per local co-member:** a `chghost` consumer gets
`:nick!old_user@old_host CHGHOST <newuser> <newhost>`; a **non-cap** member gets the
reconnect-simulation fallback `QUIT :Changing host` → per-shared-channel `JOIN` (new mask) +
server `MODE <chan> +<o/v> <nick>` (new `Channels::member_status`) — the user mid-slice required
the fallback (it was first deferred). Self-echo (cap only) is the handler return (co_members
excludes self). **S2S carrier = `ENCAP`:** `local_chghost` broadcasts `:<uid> ENCAP * CHGHOST u h`
to all peers; `forward::inbound_encap` routes the `CHGHOST` subcommand to `s2s::chghost::
apply_encap_chghost` (updates the `RemoteUser` mirror + registry + notifies local co-members; the
changed user = the message source uid, like `UMODE`) while still onward-relaying every ENCAP
verbatim (a non-CHGHOST ENCAP stays opaque — slice-35 regression guarded). **Fuzz finding:** a
leading-`:` user/host passes the typed `UserName`/`HostName` validators (idents/IPv6 admit `:`)
but can't be an IRC middle param (reparses as trailing) → the handler rejects it with a NOTICE
(defensive — the wire parser never yields such a param; the proptest builds messages directly).
Invalid input → NOTICE (no standard-replies code, avoids the slice-69 gate). Gate: cap/registry/
command(10)/s2s(6)/forward(2) units + `golden_chghost.rs` (oper+cap alice, cap bob, plain mel: bob
& self get CHGHOST, mel gets QUIT/JOIN/MODE) + `chghost_proptest.rs` (the fuzz target: command
valid-applies/invalid-inert + last-valid model; inbound tracks-last-valid + never-panics; non-CHGHOST
ENCAP inert). Plan: `…slice71-chghost.md`.

**Slice 76 (2026-06-10) shipped `utf8only`** — the `UTF8ONLY` ISUPPORT token (NOT a cap;
`isupport.rs::tokens`, before `NETWORK`) + the `INVALID_UTF8` standard reply. Before this slice
`session.rs::feed` lossy-decoded every inbound line (`from_utf8_lossy`), silently mangling
non-UTF-8 into U+FFFD and dispatching it. Now `feed` gates on `std::str::from_utf8(&line)`:
`Err` → `stdreply::fail(name, command, "INVALID_UTF8", &[], INVALID_UTF8_DESC)` + `continue` (no
dispatch); `command` = the ASCII-validated verb from a lossy parse (`*` otherwise). Sent
**unconditionally** (enabled-by-spec, like the redact FAIL — not gated on `standard-replies`).
Whole-line rejection (not content-only); no WARN/modify variant. Outbound truncation was already
char-boundary safe (`to_wire`). Additive harness `Client::send_raw(&[u8])`. **Interaction found:
the `ping_arbitrary_bytes_are_robust` proptest** asserted any non-framing token PONGs (the old
lossy contract) → split to PONG-iff-valid-UTF-8, INVALID_UTF8-otherwise (separate `test(leveva)`
commit). Regenerated the 4 full-burst 005 snapshots (UTF8ONLY joins the 2nd 005 line;
`golden_bot_mode` snapshots only the 1st line → untouched). Gate: isupport/session units +
`golden_utf8only` + `utf8only_proptest`. Plan: `…slice76-utf8only.md`.

**Slice 155 (2026-06-14) shipped `labeled-response` (+ the `batch` framing dependency)** — the
server echoes a command's inbound `@label` tag back on its **direct reply** so a client can
correlate request→reply. **Seam:** `session::Session::dispatch`'s registered arm already had the
synchronous replies as `command::dispatch() -> Vec<Message>`; that vector now feeds the pure
`leveva::labeled::wrap(enabled, label, server, batch_ref, replies)` before write — non-negotiating/
unlabeled commands pass through verbatim (common path). **Three shapes** (real ircv3.net spec, now
in `docs/rfcs/ircv3/labeled-response.md`): 0 replies → `@label :<srv> ACK`; 1 → that message gets
`@label` prepended in place; ≥2 → a `labeled-response` batch (`@label :<srv> BATCH +<ref>
labeled-response` / inners `@batch=<ref>` / `:<srv> BATCH -<ref>`). `batch_ref` = `labeled::next_ref()`
over a process-global `AtomicU64` (the `msgid::COUNTER` precedent), generated by the caller so
`wrap` stays a pure fuzz target. New `Message::with_label`/`with_batch` (the `with_server_time`
front-prepend pattern). **Advertised BOTH `labeled-response` + `batch`** in `cap.rs` SUPPORTED
(batch = the wire dependency; `ClientCaps` gained both fields; the wrap **gate is `labeled_response`
only** — `batch` is wired-but-not-read, the slice-69 `standard_replies` pattern; a future dedicated
batch slice adds OTHER batch *types* netjoin/netsplit/chathistory). **Key divergence: direct-reply
path ONLY** — async mailbox lines (`echo-message`, channel fan-out) travel `registry::deliver_uid`
and are NOT in a labeled batch (a labeled `PRIVMSG`→`ACK`, echo arrives separately untagged — which
*satisfies* the spec's self-message MUST-NOT-label rule conservatively); commands intercepted before
the seam (`QUIT`/`CAP`/pre-reg `AWAY`) aren't labeled; label echoed verbatim trusting the ≤64-byte
client contract. leveva-native (no differential — oracle predates CAP). The spec's `PONG → ACK` and
`WHOIS`-batch examples both work as-is (PONG returns `Vec::new()` from `command::dispatch`). **Pitfall
that cost time: I first hallucinated the spec doc — the user had the REAL one and replaced it; the
implementation was already correct against it.** Gate: labeled/message/cap units + `labeled_response_proptest`
(600 cases over pure `wrap`) + `golden_labeled_response` (real binary: WHOIS-batch/TIME-single/
PRIVMSG-ACK/non-negotiating-inverse) + a `batch=<REF>` canonicalizer mask; 2 `golden_cap` LS snaps
regenerated. Plan: `docs/superpowers/plans/2026-06-14-p11-slice155-labeled-response.md`.

**Slice 159 (2026-06-14) shipped SASL** — the keystone client-auth cap (`docs/rfcs/ircv3/sasl-3.2.md`).
**Architecture (user-locked decision): relay-to-services, NOT local validation** — leveva keeps no
account DB ([[iauth-subsumed-into-leveva]] / the slice-139 `ENCAP * SU` SoT), so it forwards the
**opaque** base64 `AUTHENTICATE` exchange to a linked services agent (charybdis/atheme model) and
renders the verdict. Scope = framework + **PLAIN + EXTERNAL**. Pieces: pure `leveva::sasl`
(`Mechanism{Plain,External}` + the IRCv3 400-byte chunking `chunks_for_wire`↔`Accumulator` + a
`SaslSessions` cross-task rendezvous keyed by the client's **early-assigned UID** — lives **inside
`Registry`** via `Registry::sasl()` to dodge the ~57 `ServerContext`-literal churn); a `sasl` CAPAB
token (`PeerCaps::sasl`, **never** in `ours()` — leveva isn't a provider) + `PeerLinks::sasl_agent()`;
the **first dynamically-advertised + valued client cap** (`cap.rs` `apply`/`ls`/`req` gained a
`sasl_available` arg — `sasl=PLAIN,EXTERNAL` in LS + ACK **only while an agent is linked**, else NAK,
SASL 3.2 MUST; the static `SUPPORTED` table is untouched, `sasl` is injected/filtered at render);
`session.rs` handles `AUTHENTICATE` **phase-independently** (like CAP, before the pending-complete
guard — the whole exchange runs during CAP negotiation), assigns the early UID (kept across `433`),
relays `H`/`S`(+certfp for EXTERNAL)/`C`/abort, applies the resolved account at finalize (reuse
`sasl_uid`); `s2s/sasl.rs`+`forward.rs` route the agent's inbound `ENCAP SASL C/D` + `SVSLOGIN` back
to the in-flight client (consume, don't relay). Numerics `900`–`908`. Divergences: no reauth (`907`
for a registered client), no `cap-notify` NEW/DEL of `sasl`, opaque relay (no decode/validate/cache,
no `902`), single agent. leveva-native (no differential), with a `sasl_proptest` **fuzzing** the
chunk round-trip + a real-binary `golden_sasl` (full PLAIN vs a scripted services peer → `900`/`903`/
WHOIS `330`; inverse = no agent → unadvertised/NAK/`904`). **Also fixed a latent
`metrics_endpoint_proptest` red** a prior session had left (the `["CAP"]` regressions seed): session-
layer verbs (CAP/QUIT/AUTHENTICATE) return before `command::dispatch`, the metering point, so they're
never counted — the test's QUIT-only carve-out was extended to all three. Plan:
`docs/superpowers/plans/2026-06-14-p11-slice159-sasl.md`.

**Slice 163 (2026-06-14) shipped `draft/metadata-2` (the metadata store + client command surface)**
— the **framework half** of IRCv3 [metadata](../docs/rfcs/ircv3/metadata.md) (the fresh spec the
user dropped at `docs/rfcs/ircv3/metadata.md`), mirroring the framework-vs-behavior split (48/56/69).
New **`leveva::metadata`** (pure core + store): `key_valid` (charset `a-z0-9_./-`)/`value_valid`
(`<=MAX_VALUE_BYTES`) fuzz targets; `MetaTarget{User(Uid)|Channel(folded)}`; `MetadataStore`
(`HashMap<MetaTarget,BTreeMap>` values + `HashMap<Uid,BTreeSet>` subs) **inside `Registry`**
(`registry.metadata()`, the SASL/sasl-sessions pattern → zero `ServerContext`-literal churn). New
`command/metadata.rs` `METADATA <target> GET/LIST/SET/CLEAR/SUB/UNSUB/SUBS`: GET/LIST/CLEAR reply in
a `metadata` batch (target param), SUBS in a `metadata-subs` batch (refs via `labeled::next_ref` +
`Message::with_batch`), SET/SUB/UNSUB unbatched. Numerics **761/766/770/771/772** + the METADATA
`FAIL` codes via the slice-69 `stdreply` framework. Cap `DRAFT_METADATA_2` advertised **valued** to
302+ (`draft/metadata-2=max-subs=30,max-keys=30,max-value-bytes=300` via `metadata::CAP_VALUE` — the
**first valued static-`SUPPORTED` cap**, contrast dynamic `sasl`), bare otherwise;
`ClientCaps.metadata` wired (the next-slice notification gate). **Permission (slice 163, no
privileged keys → every visibility `*`):** SET/CLEAR on self (`*`/own nick) or a channel you op
(`Channels::is_op`) else `KEY_NO_PERMISSION`; GET/LIST open. **Deferred (each a follow-on): the
notification plane** (push `METADATA` to subscribers on a watched-key change — the behavior half),
`before-connect`/registration burst, `SYNC`/`774 RPL_METADATASYNCLATER`/JOIN-sync, `760` WHOIS, S2S
propagation, rate-limiting, the privileged/visibility system; the cap isn't required to use the
command (lenient) + `batch`-dependency unenforced. leveva-native (no differential). Adding the cap to
`SUPPORTED` regenerated the full-LS asserts + `supported_names` + 2 `golden_cap` + 1 `golden_setname`
+ `golden_help_users` index snaps (METADATA added to help `COMMANDS`+index.md). Gate:
`metadata_proptest` (5 props: validators-vs-model, store-vs-`BTreeMap`, subscribe-vs-`BTreeSet`+limit)
+ `golden_metadata` (real binary, framing+correlation asserted like `golden_labeled_response`). Plan:
`docs/superpowers/plans/2026-06-14-p11-slice163-metadata.md`. **NEXT metadata slice = the
notification plane** (subscribers get `METADATA <target> <key> <vis> <value>` when a key they watch
on a channel/co-member/self/monitored-user changes).

**Remaining IRCv3 caps: SASL is now DONE (slice 159); message-tags follow-ons all done; named
independent caps DONE (`labeled-response` 155, `utf8only` 76, `extended-monitor` 74, `chghost` 71,
`monitor` 70, `standard-replies` 69 — FAIL/WARN/NOTE framework exists; future features add WARN/NOTE
callers + may gate arbitrary replies on `ClientCaps.standard_replies`). METADATA (`docs/rfcs/ircv3/metadata.md`) framework
is DONE (slice 163, store + command surface) — **next metadata slice = its notification plane**. Other
queued: a dedicated **batch** slice (chathistory type; netjoin/netsplit done 157/160), SASL **reauth**
follow-on, or pick the next P11 area with the user (see [[leveva-next-step-s2s-completeness]]).**

Added `ErrInvalidcapcmd = 410` to `numeric.rs` (slice 48); `RplWhoisbot = 335` (slice 55);
`ErrInputtoolong = 417` (slice 58). Plans:
`docs/superpowers/plans/2026-06-09-p11-slice48-cap-negotiation.md`,
`docs/superpowers/plans/2026-06-10-p11-slice51-multi-prefix.md`. Spec lives in-repo at
`docs/rfcs/ircv3/`.

**Slice 72 (2026-06-10) shipped IP cloaking (`+x`)** — a port of Elemental-IRCd's
`extensions/ip_cloaking.c`, the first non-IRCv3 *extension* on the track but it follows the
same leveva-native usermode pattern as `+W`/`+B`. New `leveva::cloak` (faithful FNV-1/32
`fnv_hash(s,32)` + `cloak_ip`/`cloak_host`/`cloak`); `UserMode::Cloak` (`+x`, `0x0100`,
appended last). Setting `+x` replaces the visible host with a deterministic cloak of the
**original connect host** (new immutable `ClientRecord.orighost`, set at `try_claim`, never
touched by `set_host`); `-x` restores it. The host change is **distributed by reusing the
slice-71 `chghost` plane** (`notify_co_members` + `local_chghost`/`ENCAP CHGHOST`) — so `+x`
is deliberately **NOT** in `SEND_UMODES` (no double-propagation; the host change is the
propagation, not the umode bit). `396 RPL_HOSTHIDDEN` added. Wire-safety invariant: `cloak`
never introduces a leading `:`. `+x` is client-settable (joins the `i|w|B` arm) AND allowed in
`default-user-modes` (network-wide auto-cloak; `config/parse.rs` now accepts `x`) — a
default-`+x` client is cloaked at registration (the C `check_new_user` path, in
`session::finalize` before the burst). **Also (user request): clients are told their user
modes on connect** — `session::finalize` emits `:nick MODE nick :+<modes>` after the welcome
burst (regenerated 4 registration snapshots: `004`→`oOiwraWBx` + the trailing MODE notice).
Gate: cloak/mode/numeric/registry/command/session/config units + `golden_ip_cloaking`
(`127.0.0.1`→`127.0.y.p`) + `cloak_proptest` (the fuzz target). Plan:
`docs/superpowers/plans/2026-06-10-p11-slice72-ip-cloaking.md`.

**Slice 78 (2026-06-10) shipped CertFP** — charybdis-style TLS client-certificate
fingerprints (researched against a fresh charybdis clone: `ircd/sslproc.c`/`m_certfp.c`/
`m_whois.c:344`/`m_oper.c:120`/`s_user.c:734`). The first **TLS-identity** feature on the
track and NOT a cap. New `leveva::certfp` (`fingerprint(der)` = lowercase-hex **SHA-256** of
the leaf cert DER via the `sha2` dep — the fuzz target; `from_peer_certs(Option<&[CertificateDer]>)`).
**Key TLS pattern: an `AcceptAnyClientCert` `ClientCertVerifier` in `tls.rs`** — requests but
does NOT require a client cert, accepts any issuer (self-signed is the norm; the fingerprint
IS the identity) while still verifying the handshake signature via the ring provider's
`signature_verification_algorithms`; `TlsEndpoint::new` switched `with_no_client_auth()` →
`with_client_cert_verifier(...)`. `main.rs` pulls `tls_stream.get_ref().1.peer_certificates()`
→ `from_peer_certs` → `serve_client(..,certfp)` → `Session::set_certfp` (new field+setter, the
`set_websocket` pattern). **Single source of truth = `ClientRecord.certfp`** (new field + new
`Registry::set_certfp`): finalize mirrors it; WHOIS and OPER read it back, so **no `Registered`
field** (dodged the ~23-literal churn). Surfaced as `276 RPL_WHOISCERTFP` (last extra-info line
before 318, local+remote). **OPER gate:** `Operator.certfp: Option<String>` (`certfp "..."`,
`opt_string`) — a block grants oper iff password verifies AND certfp matches case-insensitively;
a name+host+password match that fails certfp → **491** (charybdis parity), distinct from the
464 password arm (precedence flag `certfp_mismatch`). **S2S = `ENCAP * CERTFP`** (new
`s2s/certfp.rs::apply_encap_certfp` + `forward.rs` arm + burst appends `:<uid> ENCAP * CERTFP
:<fp>` per local certfp user) — the slice-71 CHGHOST relay pattern (record source uid + onward-
relay verbatim). Divergences: **sha256-only** (charybdis defaults to deprecated sha1 + a method
menu); single-server-local notify (burst carries it, no live post-burst rebroadcast — leveva has
no live UNICK introduce); `RemoteUser` untouched (WHOIS reads the registry record UNICK populates).
**Gate incl. the crown-jewel `golden_certfp.rs`: a REAL TLS handshake** (`rcgen`-generated
server+client certs as dev-deps, a synchronous `rustls::StreamOwned` client presenting the
client cert) against a booted leveva → WHOIS 276 == independently-computed SHA-256 + certfp-
gated OPER → 381. Plus `certfp_proptest.rs` + oper/whois/session/s2s units. Adding a 4th field
to `Operator` touched 4 `tests/*_proptest.rs` literals (kill/oper/oper_tag/wallops → `certfp:
None`). Plan: `docs/superpowers/plans/2026-06-10-p11-slice78-certfp.md`.

**BATCH track:** the `batch` cap is advertised (slice 155) and now produces TWO types:
`labeled-response` (155, `leveva::labeled::wrap` over the direct-reply vector) and **`netsplit`
(slice 157, 2026-06-14)** — `leveva::s2s::squit::netsplit_frame` wraps a server-split's QUIT flood
in one batch per `batch`-capable local co-member, gated on `caps_of(recipient).batch`. The shared
ref source is `labeled::next_ref` (process-global hex counter; per-connection). `squit_subtree` was
restructured inline-deliver → per-recipient collect→deliver (split teardown helpers keep the single
relayed-QUIT path immediate; non-batch recipients byte-identical). **`netjoin` is the deferred
follow-on** (spread across many `NJOIN` calls during a burst → needs cross-message buffering until
EOB, a distinct mechanism); `chathistory` needs a history store leveva lacks. The slice-156 "NEXT =
ask the user" list (SASL keystone / a batch slice / SendQ hardening / other IRCv3 caps) — batch is
now partly done (netsplit) and **SASL is DONE (slice 159)**; next IRCv3 candidate is METADATA
(the new `docs/rfcs/ircv3/metadata.md`).

**Slice 211 (2026-06-16) shipped `sts`** (IRCv3 Strict Transport Security) — the first cap on
an **STS/TLS track**. It is **advisory-only**: stays *out* of the `SUPPORTED` registry (so
`CAP REQ sts` NAKs and it never shows in `CAP LIST`) and is injected directly into the `LS`
token list, **302+ only** (a bare valueless `sts` is useless). Pure core `sts::StsPolicy {
duration, port, preload }` + `ls_value(secure) -> Option<String>`: `None` (disabled) unless a
TLS client listener exists *and* `duration != 0`; plaintext → `port=<p>` (upgrade), TLS →
`duration=<d>[,preload]` (persist; preload never over plaintext, per spec). Config
`options { sts-duration N; sts-preload }` (boot-read, default off, `0` = off). Lives on
`StatsConf.sts` (slice-206 churn-free bundling); `from_config` derives the port from the first
`tls && !server_only && websocket.is_none()` listener. New `Session.secure` flag set by
`serve_client` (TLS arm true / plaintext false) drives the per-connection token; `cap.apply`
gained an `sts: Option<&str>` param. **Documented follow-ons:** REHASH-ability of the knobs +
the TLS port (boot-read for now, the flood 201→204 rhythm); wss connections advertised as
insecure (the secure-flag plumbing for the websocket path is out of scope). Gate: sts/cap/config
units + `tests/sts_proptest.rs` + `tests/golden_sts.rs`.

**Slice 221 (2026-06-16) shipped `760 RPL_WHOISKEYVALUE`** — `draft/metadata-2` metadata in
`WHOIS`. A WHOIS on a user with metadata set now emits `:<srv> 760 <requester> <target> <key>
<vis> :<value>` lines, **gated on the requester's `client.caps.metadata`** (no cap → no 760, the
inverse), one per key in sorted `MetadataStore::list` order, before the
317/318 tail; fires for remote targets too (metadata is UID-keyed + network-wide via the
slice-189 burst / slice-177 propagate). Pure fuzz seam `command::whois::whois_keyvalue_lines`.

**Slice 223 (2026-06-16) shipped the privileged-key / restricted-visibility system** — the
**last** `draft/metadata-2` deferral (named by slice 221). A metadata key is *oper-restricted*
(settable/viewable only by `+o`/`+O`, visibility token `oper` not `*`) iff it begins with the
built-in `priv.` prefix (`metadata::PRIV_KEY_PREFIX`) **or** matches a REHASH-able
`options { oper-keys "<glob>" }` allowlist (user-locked *prefix+config* scheme; the
slice-204/210/212 `ConfStore` `live_oper_keys` seam — `Options.oper_keys` →
`ConfBlocks`/`ConfStore` `ArcSwapOption<Vec<String>>`, REHASH auto-reseeds via `config_conf`).
A non-oper is refused SET/GET (`KEY_NO_PERMISSION`), omitted from LIST/760 WHOIS, skipped by
CLEAR (non-oper CLEAR clears only non-restricted keys via per-key `remove`, not the blanket
`clear`), and never pushed a restricted key via `notify_subscribers` (covers the local +
inbound-S2S `s2s::metadata::apply_encap_metadata` paths — they share the fn). **Pure fuzz seam =
`metadata::key_visibility(key, oper_keys) -> Visibility{Everyone,Oper}`** (label `*`/`oper`,
`is_restricted`); `whois_keyvalue_lines` + `rpl_keyvalue` gained a visibility param. Gate adds the
config-driven `golden_metadata_priv` (real binary booted with `oper-keys` + an `operator` block:
opered alice sets `priv.note`+`secret-score`→`761 oper`, mortal bob can't SET/GET/LIST them) +
the `metadata_proptest` `key_visibility_is_total_and_contractual` fuzz. **The `draft/metadata-2`
track is now feature-complete except `SYNC`/`774`/`RATE_LIMITED`** (still deliberately out of
scope). Also corrected two stale doc comments ("no registration metadata burst" — slice 189 added
it; "no privileged-key visibility"). Plan:
`docs/superpowers/plans/2026-06-16-p11-slice223-metadata-privileged-keys.md`.
