Crate: kinetic-core
Stage: 3
Reading Time: 45 mins
Depends On: api_error.rs, vdf.rs, constants.rs
What Is This?
This documentation covers the file kinetic-core/src/error/dht.rs.
This file is the definitive, comprehensive taxonomy of error states for the Kademlia Distributed Hash Table (DHT) within the Kinetic network.
It is responsible for defining the exhaustive list of failure modes that can occur during the highly complex, multi-stage lifecycle of managing decentralized .kin names on the peer-to-peer network.
The file maps low-level peer-to-peer networking failures, cryptographic proof rejections, and state transition errors into a standardized, RFC-7807-compliant API error taxonomy.
At its core, this file provides four primary enumerations that correspond to the four major phases of interaction with the DHT. The four primary enumerations are:
RecordRejectReason: The internal, fine-grained reasons why the local node’sKineticRecordStoremight refuse to store an incoming DHT record from a remote peer.ResolutionError: The errors that can occur when a user or client application attempts to look up a.kinname and read its associated data from the network.PublishError: The errors that can occur when the local node attempts to broadcast a new or updated record out to the wider DHT.RegistrationError: The high-level orchestrator errors that encapsulate the entire two-phase commit-reveal process of claiming a new.kinname.
By centralizing these error definitions, Kinetic ensures that front-end clients, mobile applications, and CLI tools receive consistent, actionable feedback whenever a decentralized operation fails. It eliminates the ambiguity of generic network errors.
Why Kinetic Needs This
In standard centralized web architecture (often referred to as Web2), errors are usually straightforward, binary, and absolute. A database row doesn’t exist (HTTP 404), a server is down (HTTP 503), or a payload is malformed (HTTP 400). In these models, you trust the server’s response implicitly because the server is the single source of truth.
In a peer-to-peer network like Kinetic, failure is not just common; it is the default operating environment. A DHT operation can fail for dozens of nuanced reasons that have no equivalent in traditional client-server models. Consider the act of registering a name on the Kinetic network. A peer routing your request might go offline halfway through the process. A cryptographic verifiable delay function (VDF) might be spoofed by a malicious actor attempting to squat on a name. A temporary network partition might cause the DHT to split, leading to inconsistent state across the swarm. Two completely honest users might try to register the exact same name at the exact same drand (distributed randomness) round, resulting in a cryptographic tie-break.
Without a highly granular, robust error taxonomy, the Kinetic node would be forced to emit generic, opaque errors like “connection closed”, “validation failed”, or “Kademlia timeout”. This leaves developers and end-users completely blind to what actually went wrong and, more importantly, how to fix it. If a user spends ten minutes computing a VDF only for it to fail, they need to know exactly why so they don’t waste another ten minutes.
Kinetic requires an error system that bridges the gap between Byzantine network failures and user experience. It must distinguish between a temporary network timeout (which should be retried automatically by the client) and a cryptographic forgery (which means the data is poisoned and must be immediately discarded). Furthermore, because Kinetic uses a dynamic difficulty adjustment system for its VDFs, an error might not just indicate a failure, but an instruction. For example, it might tell the client that their proof was mathematically valid, but the difficulty threshold has increased, and they need to compute the VDF for more iterations.
This specific file translates peer-to-peer networking and verifiable delay functions into predictable, actionable API errors.
Every error has a stable RFC 7807 compatible code (e.g., KIN-RES-003), a user-friendly message that strips away technical jargon, a severity level for telemetry and monitoring, and a boolean flag indicating whether the operation is safe to retry.
This transforms the decentralized backend into something predictable for frontend developers, completely hiding the complex peer-to-peer reality underneath.
How It Works
The architecture of this file is divided into four main functional areas, each represented by a distinct Rust enum.
These enums use the thiserror crate to automatically implement the standard std::error::Error trait, while also providing custom methods that map the errors into the Kinetic standard taxonomy.
We will break down how each phase operates, the specific variants it contains, and the theoretical concepts underpinning them.
1. Local Store Validation (RecordRejectReason)
-> See: kinetic-core/src/error/dht.rs — Lines 18 to 52
In a Kademlia DHT, nodes are constantly asking each other to store data.
When a remote peer sends a PUT request to our local Kinetic node, our node cannot blindly accept and store the payload.
If it did, malicious actors could easily fill our hard drive with garbage data or overwrite legitimate .kin name registrations.
To prevent this, the KineticRecordStore acts as a strict gatekeeper.
It evaluates every single incoming record against the consensus rules of the Kinetic naming protocol.
If the record violates any rule, it is immediately dropped, and a RecordRejectReason is returned to the sender.
This enum does not map directly to a KIN-* error code because it is an internal p2p protocol mechanism, not something typically surfaced directly to an end-user client.
However, it may be wrapped by a PublishError or RegistrationError later in the stack.
The validation checks happen in a specific order to minimize computational waste. They are detailed below:
InvalidSignature (Line 23)
- This error is triggered if the payload’s Ed25519 signature does not verify against the claimed public key.
- It indicates that the record was likely tampered with in transit by a malicious intermediary.
- Alternatively, it means the sender is attempting to forge a record for a public key they do not own.
- This is a fatal cryptographic failure and the record is immediately discarded.
- It prevents unauthorized users from hijacking names that do not belong to them.
InvalidVdf (Line 26)
- This error occurs when the mathematical proof provided in the record fails the verification algorithm.
- Kinetic relies on Verifiable Delay Functions (VDFs) to prove that real-world time has elapsed.
- If the Wesolowski proof is mathematically invalid, it means the sender tried to bypass the time delay.
- This immediately flags the sender as a malicious actor attempting a Sybil or squatting attack.
- The record is dropped to protect the integrity of the naming system.
Expired (Line 29)
- Records in Kinetic are not permanent; they are tied to specific drand rounds and epochs.
- If a record is submitted, but the epoch it belongs to has already passed into history, it is no longer valid.
- The network considers it stale and purges it, returning this expiration error.
- This mechanism keeps the DHT clean of ancient, irrelevant data.
- It also ensures that users must periodically renew their names to maintain ownership.
AlreadyOwned (Line 32)
- This error is returned when a node attempts to claim a name that is already fully registered.
- The local store checks its existing records and sees that another public key holds the claim.
- Because the epoch has closed, the existing claim is unassailable.
- The incoming record is rejected, and the sender is informed that they are too late.
- This enforces the fundamental rule that a name can only have one owner at a time.
InsufficientIterations (Line 36)
- Kinetic enforces a dynamic difficulty for its VDFs based on network demand and name length.
- If the proof is mathematically valid, but the number of iterations is too low, this error is thrown.
- It means the sender did not compute the VDF for long enough to meet the current threshold.
- This stops attackers from using trivial, instantaneous proofs to bypass the required delay.
- The client must recalculate the VDF with a higher iteration count and try again.
TieBroken (Line 39)
- In a decentralized network, two honest users might generate valid proofs for the same name at the same time.
- The network must resolve this collision deterministically using the Kademlia XOR distance metric.
- The node takes the hash of the data payload and XORs it with the hash of the name.
- The record that results in the mathematically smaller XOR distance wins.
- The loser is rejected with this error, guaranteeing consensus without centralized arbitration.
CommitmentMismatch (Line 42)
- To prevent front-running, Kinetic uses a two-phase commit-reveal scheme.
- A user first publishes a hashed commitment of their key, and later reveals the key itself.
- When evaluating a reveal record, the store hashes the revealed key and compares it to the stored commitment.
- If they do not match exactly, this error is thrown.
- This prevents an attacker from hijacking a commitment that was secured by someone else.
InvalidDrandHex (Line 45)
- Kinetic uses drand (distributed randomness) beacons to seed the VDF computation.
- The beacon signature must be passed as a valid hexadecimal string.
- If the string contains non-hex characters, this error is triggered before any expensive math is done.
- This is a fast-fail structural check.
- It protects the node from panicking while trying to parse garbage data.
InvalidPublicKey (Line 48)
- The record must contain the owner’s Ed25519 public key.
- If the provided bytes cannot be parsed into a valid point on the elliptic curve, this error occurs.
- Like the hex check, this is a fast-fail structural validation.
- It prevents the cryptographic library from crashing on malformed input.
- Malformed keys are instantly dropped.
MalformedSignature (Line 51)
- An Ed25519 signature must be exactly 64 bytes long.
- If the byte array is the wrong length, this error is returned.
- This is the cheapest and fastest check the node performs.
- It acts as the first line of defense against badly formatted packets.
- Records failing this check are discarded immediately.
2. DHT Resolution Phase (ResolutionError)
-> See: kinetic-core/src/error/dht.rs — Lines 54 to 188
When a client application needs to know the public key associated with alice.kin, it asks the local node to resolve the name.
The node executes a Kademlia DHT GET operation, crawling the network to find the peers closest to the hash of the name.
The ResolutionError enum captures all the ways this read operation can fail.
These errors are directly surfaced to the client via the API boundary. Therefore, the enum implements specific methods to conform to the Kinetic API taxonomy.
- The
code()method (Line 110) returns the stable identifier (e.g.,KIN-RES-001). - This ensures frontend code can switch on a stable string rather than parsing error messages.
- The
error_type_uri()method (Line 122) appends the code to the base docs URL to create an RFC 7807 compliant type URI. - This allows developers to click a link in their API response and read the documentation for that specific error.
- The
is_retryable()method (Line 127) is a crucial boolean. - If true, the frontend client should automatically initiate a retry with exponential backoff.
- For example, timeouts are retryable, but missing data is not.
- The
severity()method (Line 132) maps the error to a logging severity (Info, Warning, Error). - A missing record is an
Infoevent, as it’s standard operating behavior. - An internal panic is an
Errorevent requiring developer attention. - The
user_message()method (Line 144) provides a clean, sanitized string meant to be displayed directly in a UI alert box. - It strips away all mentions of “Kademlia,” “DHT,” and “VDFs.”
- Finally, the
details()method (Line 171) packages developer-centric metadata into aserde_json::Valueobject. - This allows the frontend to access structured data without parsing strings.
The variants cover the reality of network reads in a potentially hostile environment:
Offline (Line 62 / KIN-RES-001)
- The node’s libp2p swarm has exactly zero active connections to the outside world.
- The DHT cannot be reached at all because there are no peers in the routing table.
- The node is effectively isolated in a silo.
- The operation aborts immediately without attempting to send packets.
- The client should prompt the user to check their internet connection or firewall settings.
NotFound (Line 65 / KIN-RES-002)
- The crawler successfully contacted the closest peers, but none of them had the record.
- This means the name is currently available for registration.
- The
peers_queriedfield indicates how exhaustive the search was before the node gave up. - This is not a fatal error; it is an informational response.
- The UI should simply display a message stating that the name is unregistered.
VdfVerificationFailed (Line 73 / KIN-RES-003)
- This is a critical security feature built into the resolution process.
- If the node successfully retrieves a record from the DHT, it does not inherently trust it.
- It must verify the VDF proof locally using the
chiavdfverifier. - If a malicious peer hands us a forged record, the resolution process aborts and throws this error.
- The
countfield indicates how many fake records were discarded during the query.
Expired (Line 80 / KIN-RES-004)
- The record was found on the network, and its mathematical proofs are entirely valid.
- However, its associated drand epoch has passed into history.
- The registration is no longer legally binding on the network, and the owner must renew it.
- The
agefield shows how old the record is in rounds, giving the UI context on exactly how stale it is. - The UI should display the name as available for claim, allowing a new user to overwrite the old data.
Timeout (Line 89 / KIN-RES-005)
- The asynchronous Kademlia query exceeded the maximum allowed wall-clock time.
- This frequently happens in highly congested networks or during widespread packet loss.
- It can also occur if the local routing table is heavily polluted with dead or unresponsive nodes.
- This variant includes
elapsed_msandpeers_queriedto aid in debugging telemetry. - It is fully retryable, meaning a client should automatically try again after a brief exponential backoff.
Internal (Line 98 / KIN-RES-006)
- An unexpected panic, filesystem error, or underlying library failure occurred on the local machine.
- This contains a developer
messageexplaining the nature of the fault. - It also optionally contains a boxed trait object for the source error to trace the root cause.
- It indicates a bug or hardware issue on the local node itself, not a network protocol problem.
- This should ideally trigger an automated crash report or alert the user to restart the node.
3. DHT Publishing Phase (PublishError)
-> See: kinetic-core/src/error/dht.rs — Lines 190 to 286
Writing to a Kademlia DHT is significantly more complex than reading.
A read only requires finding one honest peer with the data.
A write requires convincing a quorum of the k closest peers to accept and store the data simultaneously.
The PublishError enum tracks the failure modes of the Kademlia PUT lifecycle.
Like resolution errors, these are mapped to stable API codes, in this case prefixed with KIN-PUB.
Before a record is even broadcast over the wire, it undergoes a sanity check on the local node. This prevents the node from spamming the network with invalid data and wasting bandwidth.
Offline (Line 197 / KIN-PUB-001)
- Similar to the resolution phase, the node checks if it has any connected peers.
- If the local node is entirely isolated from the network, it immediately returns this error.
- No network traffic is generated.
- The client should inform the user that they must connect to the network before publishing.
- This is a transient error and is safe to retry once connectivity is restored.
InvalidProof (Line 200 / KIN-PUB-002)
- Before broadcasting, the local node verifies the VDF proof it just generated or received.
- If the node realizes the VDF proof attached to the outbound record is mathematically broken, it aborts early.
- It wraps the underlying
VdfRejectReasonto provide specific context. - This shouldn’t happen under normal operation but serves as a safety net against local logic bugs.
- It guarantees the node never willingly pollutes the network with invalid data.
AlreadyOwned (Line 203 / KIN-PUB-003)
- The local node checks its own local cache before initiating a costly network broadcast.
- If it realizes the name is already firmly owned by a different key, it throws this error.
- This saves significant bandwidth and prevents an inevitable rejection from the remote peers.
- It serves as a fast-fail optimization for the publish pipeline.
- The client should be instructed to pick a new name.
AllFailed (Line 209 / KIN-PUB-004)
- In a Kademlia network, a
PUToperation broadcasts the record to multiple peers simultaneously. - A publish is generally considered successful if at least a specific quorum of those peers accept it.
- However, if every single peer contacted explicitly rejects the record, the operation fails completely.
- This can happen if our local clock is wildly out of sync or if we are running an incompatible protocol version.
- The
countfield tells the developer exactly how many peers slammed the door in our face.
Rejected (Line 215 / KIN-PUB-005)
- When a specific peer rejects the message, it returns a
RecordRejectReason(likeTieBroken). - If this rejection causes the overall publish quorum to fail, it is mapped into this generic variant.
- The inner string allows the local node to log the remote peer’s exact justification.
- This is incredibly useful for debugging why the network at large is refusing to accept our valid data.
- It provides a window into the consensus state of the remote nodes.
Internal (Line 217 / KIN-PUB-006)
- This catches unforeseen local errors during the complex asynchronous broadcast phase.
- Examples include serialization failures, memory allocation issues, or async executor thread panics.
- It contains a developer message and an optional source error.
- It indicates a severe local malfunction rather than a network protocol issue.
- This error is generally not retryable, as the local state is likely corrupted.
4. High-Level Registration Flow (RegistrationError)
-> See: kinetic-core/src/error/dht.rs — Lines 288 to 393
While resolution and publishing deal with atomic, individual DHT RPCs, registration represents the overarching business logic of claiming a .kin name.
This is a complex saga involving multiple coordinated operations over several minutes.
It involves validating syntax, fetching drand beacons, computing VDFs, and orchestrating the commit-reveal flow.
The RegistrationError enum encapsulates the failures of this entire long-running saga.
It utilizes stable KIN-REG-NNN codes.
Because this process is highly user-facing, these errors are the most likely to be seen by an end-user.
InvalidName (Line 295 / KIN-REG-001)
- This is the very first gate in the registration process.
- If the user requests a name with uppercase letters, emojis, or spaces, the process halts immediately.
- The Kinetic protocol enforces strict lowercase alphanumeric and hyphen rules to prevent homograph attacks.
- The user message explicitly tells them to use valid characters (Line 374).
- No network requests are made; this is a pure local validation failure.
VdfFailed (Line 301 / KIN-REG-002)
- Computing a VDF is an intensely heavy operation handled by an external C++ library (
chiavdf). - If that external process panics, runs out of memory, or returns a mathematical error, it is caught here.
- This variant explicitly wraps the underlying
VdfRejectReason. - Note that
is_retryable()returnstrueonly for this variant (Line 355). - A transient hardware glitch during computation is worth retrying automatically.
CommitmentMismatch (Line 304 / KIN-REG-003)
- During the reveal phase, the orchestrator checks its data before broadcasting.
- If it realizes that the reveal data does not hash to the commitment it previously broadcast, it halts.
- This represents a severe inconsistency in local state.
- It is perhaps caused by the client switching keys mid-registration or a database corruption.
- This is a fatal logic error and the registration must be restarted from scratch.
AlreadyOwned (Line 307 / KIN-REG-004)
- The name was available when the client started computing the 10-minute VDF.
- However, by the time the VDF finished, someone else had successfully claimed the name and locked the epoch.
- The client was literally beaten to the punch because a competitor started calculating their proof earlier.
- The UI should instruct the user to choose a different name entirely.
- The computation time was unfortunately wasted, which is a known risk in decentralized systems.
AlreadyInProgress (Line 312 / KIN-REG-005)
- This is a vital concurrency guard for the node’s resources.
- VDF computation consumes significant CPU cycles and can run for minutes.
- The node must aggressively prevent users from accidentally clicking “Register” twice.
- If a task for
alice.kinis already in the orchestrator’s state map, a second request immediately returns this error. - This prevents the machine from starving itself of resources.
NetworkRejected (Line 319 / KIN-REG-006)
- This is a powerful wrapper around the lower-level store errors.
- If the final
PUTstep fails, the low-levelRecordRejectReason(likeTieBroken) is bubbled all the way up. - It is wrapped in this variant so the UI knows exactly why the registration failed at the literal finish line.
- The
details()method expertly extracts the underlying reason string into a JSON payload (Line 388). - This provides deep visibility into network consensus failures directly to the client.
Internal (Line 324 / KIN-REG-007)
- The standard catch-all for orchestrator panics, channel communication failures, or local disk errors.
- It handles issues that don’t fit anywhere else in the taxonomy.
- It provides developer context and stack trace information if available.
- It indicates a severe local malfunction requiring developer attention.
- It is explicitly not retryable.
5. Deep Dive: serde_json::Value and RFC 7807
One of the most powerful aspects of this error file is how it extracts internal Rust struct data and formats it into standard JSON.
If an error happens on a node, but the user is using a web dashboard, the web dashboard doesn’t understand Rust memory layouts.
It understands JSON.
The details() method on these enums explicitly maps internal fields to a serde_json::Value (a dynamic JSON tree).
The details() method extracts internal struct data and formats it into standard JSON.
Instead of forcing the client to parse strings, details() returns structured data.
This conforms to RFC 7807, defining standard schemas for problem details.
-> See RUST_CONCEPTS.md for explanations of how the thiserror crate operates and how PartialEq is manually implemented for external crate types (like std::error::Error).
7. Deep Dive: Decoding the XOR Tie-Break Mechanism
The RecordRejectReason::TieBroken variant is an artifact of decentralized consensus.
When two people register a username simultaneously, there is no global clock to order them.
Kinetic resolves this using the XOR distance metric between the name hash and the public key hash.
Whichever key is closer to the name hash wins; the loser receives a TieBroken error.
8. Deep Dive: Logging Severities
The severity() method maps errors to standard levels:
- Info: Expected protocol states (e.g.,
NotFound). - Warning: Transient network issues or peer behavior (e.g.,
AllFailed). - Error: Failures requiring intervention (e.g.,
VdfVerificationFailed,Internal).
9. Deep Dive: Exponential Backoff Strategies
The is_retryable() flag informs the client if a request should be retried using exponential backoff.
This prevents network congestion from being exacerbated by constant automated retries.
Key Pieces
RecordRejectReason
- What it is: Low-level reasons a
KineticRecordStorerefuses to save a DHT record. - File & Line:
kinetic-core/src/error/dht.rs— Lines 18 to 52 - Why it matters: It is the primary, frontline defense against spam, Sybil attacks, and invalid state transitions in the peer-to-peer network.
- Impact: Without these stringent checks, the distributed hash table would instantly fill with unverified garbage data.
ResolutionError
- What it is: The rich error enum specifically tailored for the
GET(read) path of the DHT. - File & Line:
kinetic-core/src/error/dht.rs— Lines 54 to 188 - Why it matters: It maps asynchronous Kademlia lookup failures—like timeouts, missing records, or cryptographically forged data—into the stable
KIN-RESAPI taxonomy. - Impact: This allows frontends to handle them gracefully without needing to understand the underlying libp2p implementation details.
PublishError
- What it is: The rich error enum specifically tailored for the
PUT(write) path of the DHT. - File & Line:
kinetic-core/src/error/dht.rs— Lines 190 to 286 - Why it matters: It captures complex multi-peer quorum failures (like
AllFailed) and offline states when the local node attempts to broadcast data. - Impact: It utilizes the
KIN-PUBcode prefix and provides structured feedback for write operations.
RegistrationError
- What it is: The highest-level error enum governing the complex, multi-minute commit-reveal flow.
- File & Line:
kinetic-core/src/error/dht.rs— Lines 288 to 393 - Why it matters: This is the error type that the application orchestrator returns directly to the user client.
- Impact: It handles UX-centric problems like concurrency (
AlreadyInProgress), user typos (InvalidName), and hardware computation failures (VdfFailed). It uses theKIN-REGcode prefix.
code(), severity(), and is_retryable() Methods
- What it is: A suite of methods implemented on all three rich error enums.
- File & Line: Scattered throughout the file, e.g., Line 110, 127, 132.
- Why it matters: These methods mathematically enforce the Kinetic error taxonomy.
- Impact: They guarantee that every error can be deterministically categorized, logged with the correct urgency level, and automatically retried by the frontend if appropriate, removing guesswork for client developers.
details() Method
- What it is: A method implemented on the rich error enums returning a
serde_json::Value. - File & Line: Scattered throughout the file, e.g., Line 171, Line 279, Line 385.
- Why it matters: This allows the error taxonomy to pass strongly typed, structured metadata (like
peers_queried,elapsed_ms, orage_rounds) across the FFI or HTTP boundary. - Impact: This prevents frontends from having to parse fragile string messages with Regex to figure out what happened.
How This Connects to the Rest of Kinetic
FORWARD DEPENDENCY: The API Layer Boundary
These errors are explicitly designed not to live in isolation deep within the core logic.
They are built to be seamlessly converted into the generic ApiError struct (defined elsewhere in the kinetic-core crate).
The methods implemented on these enums (code(), user_message(), and details()) align perfectly with the fields required to construct a standard RFC-7807 JSON error response.
This response is then sent over the local HTTP server to a web interface, or passed across the Foreign Function Interface (FFI) boundary to a mobile application or desktop GUI.
This boundary is the primary consumer of this file.
CROSS-CRATE: chiavdf and drand Primitives
The VdfFailed variants intimately connect this error system to the heavy C++ VDF bindings provided by the chiavdf integration.
Furthermore, the InvalidDrandHex and Expired variants rely entirely on the network’s understanding of the global, decentralized drand beacon schedule.
This error module assumes the absolute existence and correctness of these external cryptographic primitives and provides the necessary error-handling glue for when they inevitably fail or time out.
CROSS-CRATE: libp2p-kad Abstracted
The AllFailed variant in PublishError and the NotFound variant in ResolutionError are direct abstractions over the success/failure thresholds of the libp2p crate’s Kademlia routing table.
These errors hide the immense complexity of iterative routing queries, XOR distance metrics, and K-bucket evictions from the rest of the application, surfacing only the actionable outcome.
Quick Reference
| Code Prefix | General Description | Example Triggers |
|---|---|---|
| KIN-RES-* | Resolution (Read) Errors | Node offline, name not found, VDF mathematically spoofed, Kademlia lookup timeout. |
| KIN-PUB-* | Publish (Write) Errors | Network partitioned, quorum rejected the PUT, invalid local proof before broadcast. |
| KIN-REG-* | Registration (Flow) Errors | Invalid characters in name, VDF thread crashed, registration already in progress. |
| N/A | RecordRejectReason | Internal p2p rejection (XOR TieBroken, CommitmentMismatch). No API code associated. |
Open Questions / Things to Revisit
- Drand Dependency Errors: There is currently no explicit error variant for “The drand network is unreachable.”
- Retrieving the latest beacon is a strict prerequisite for generating a VDF and starting a registration.
- If drand fails, it likely bubbles up as an opaque
Internalerror. - We should critically consider adding a specific
DrandUnreachablevariant toRegistrationErrorso the UI can tell the user that the global randomness beacon is down, rather than displaying an internal panic message.
Box<dyn Error>Equality Checks: The manualPartialEqimplementation forInternalvariants ignores the boxed underlying source error and only compares the developermessagestring.
- This is generally fine for unit testing the outer enum, but it is technically a lossy comparison.
- We might want to explore using a crate like
dyn-cloneor switching toanyhowif we ever need strict, deep equality checks on internal errors for complex test scenarios.
- Hardcoded Timeout Visibility:
ResolutionError::Timeoutcurrently reportselapsed_ms.
- The actual timeout duration is defined as a constant elsewhere in the codebase.
- It might be highly useful to include the configured maximum timeout in the
details()JSON payload, so clients know exactly what threshold was breached and can adjust their expectations or retry policies.
- Tie-Break Visibility:
RecordRejectReason::TieBrokenis currently swallowed by the genericRegistrationError::NetworkRejected.
- A client whose registration fails because they lost a legitimate XOR tie-break might benefit from knowing exactly who beat them (e.g., returning the winning public key and their iteration count in the error details).
- Currently, this valuable debugging data is dropped entirely by the orchestrator.