RegisterDelegate has no docs, and RegisterDelegateWithPredecessors says secrets are "sealed client-side"
src/client_api/client_events.rs (0.8.5):
-
DelegateRequest::RegisterDelegate (line 591) has no rustdoc at all. It carries cipher: [u8; 32] and nonce: [u8; 24], and it is the first thing an integrator reads when deciding what to put in those fields.
-
RegisterDelegateWithPredecessors (lines 615-619) documents the ignore, but explains it wrongly:
cipher and nonce mirror [DelegateRequest::RegisterDelegate] purely for field-shape parity. The node has ignored both since freenet-core#4140 (secrets are sealed client-side), so they carry no behavior here either.
The parenthetical is not true. Delegate secrets are sealed by the node, under a per-delegate DEK the node derives with HKDF-SHA256(salt = delegate key, ikm = node KEK) — see SecretsStore::derive_delegate_dek in freenet-core. The node holds the plaintext during store_secret and re-derives the key on every read. The reason the client's cipher is ignored is the opposite of client-side sealing: accepting a client-supplied key would let a malicious or buggy client substitute a key the node operator does not control.
Why it matters
0.8 removed DelegateRequest::DEFAULT_CIPHER / DEFAULT_NONCE, so every app bumping 0.6 → 0.8 has to decide what to send in their place. The honest answer is "any value, the node discards it". A reader who lands on the current text concludes either that the bytes are load-bearing key material worth persisting (from the undocumented variant), or that the node never sees their plaintext (from the parenthetical). Both lead somewhere wrong, and the second is the more dangerous, since it overstates a security property.
This is the stdlib half of freenet/freenet-core#5265, where the equivalent stale claims in core have been corrected (freenet/freenet-core#5472). Core can't close this one: an integrator reads the stdlib types first.
Suggested fix
Give RegisterDelegate a rustdoc saying cipher/nonce are retained for wire-format compatibility and discarded by the node, which derives the delegate's local-scope DEK from its own KEK — so any value works, including all-zero bytes (the fields are fixed-size, so "any value" means any bytes, not an empty slice). Then drop the "sealed client-side" parenthetical from RegisterDelegateWithPredecessors and point both at the same explanation. Citing freenet-core#4146 alongside #4140 makes the history findable.
[AI-assisted - Claude]
RegisterDelegatehas no docs, andRegisterDelegateWithPredecessorssays secrets are "sealed client-side"src/client_api/client_events.rs(0.8.5):DelegateRequest::RegisterDelegate(line 591) has no rustdoc at all. It carriescipher: [u8; 32]andnonce: [u8; 24], and it is the first thing an integrator reads when deciding what to put in those fields.RegisterDelegateWithPredecessors(lines 615-619) documents the ignore, but explains it wrongly:The parenthetical is not true. Delegate secrets are sealed by the node, under a per-delegate DEK the node derives with
HKDF-SHA256(salt = delegate key, ikm = node KEK)— seeSecretsStore::derive_delegate_dekin freenet-core. The node holds the plaintext duringstore_secretand re-derives the key on every read. The reason the client's cipher is ignored is the opposite of client-side sealing: accepting a client-supplied key would let a malicious or buggy client substitute a key the node operator does not control.Why it matters
0.8 removed
DelegateRequest::DEFAULT_CIPHER/DEFAULT_NONCE, so every app bumping 0.6 → 0.8 has to decide what to send in their place. The honest answer is "any value, the node discards it". A reader who lands on the current text concludes either that the bytes are load-bearing key material worth persisting (from the undocumented variant), or that the node never sees their plaintext (from the parenthetical). Both lead somewhere wrong, and the second is the more dangerous, since it overstates a security property.This is the stdlib half of freenet/freenet-core#5265, where the equivalent stale claims in core have been corrected (freenet/freenet-core#5472). Core can't close this one: an integrator reads the stdlib types first.
Suggested fix
Give
RegisterDelegatea rustdoc sayingcipher/nonceare retained for wire-format compatibility and discarded by the node, which derives the delegate's local-scope DEK from its own KEK — so any value works, including all-zero bytes (the fields are fixed-size, so "any value" means any bytes, not an empty slice). Then drop the "sealed client-side" parenthetical fromRegisterDelegateWithPredecessorsand point both at the same explanation. Citing freenet-core#4146 alongside #4140 makes the history findable.[AI-assisted - Claude]