fix(rpc): source the shell error catalogue from dig-rpc-protocol so -32004 carries one name - #494
Conversation
…32004 carries one name The shell published `RESOURCE_NOT_AVAILABLE_AT_ROOT` for -32004 while every frame the node emits carries `RESOURCE_UNAVAILABLE` — a generated client would match a name no frame has ever had. The long name had zero producers, so this is a discovery-document lie rather than a wire break, and no dig-rpc-protocol change is needed. Every code the shell shares with the contract crate now takes its number and machine string from `dig_rpc_protocol::ErrorCode` instead of restating it. -32000 is excluded and tracked on #496: the shell mints DISPATCH_FAILED itself, so that name IS on the wire. The catalogued origin for -32004 becomes `node`: the node library mints it on an ordinary local miss, so claiming `upstream` was a second untruth in the same row. Closes #478
|
docs.dig.net sweep, full-tree denominator (the body cites the
Both numbers agree on the load-bearing claim: nothing in docs.dig.net publishes the name this PR removes, so §4.3 needs no docs change. |
loop-reviewer — IN PROGRESS, not the verdictHead audited: Confirmed so far:
One finding is forming on |
loop-security: IN PROGRESS — not the verdictAudited head: Cleared so far1. No numeric re-mapping. No auth code silently re-coded. The primary risk of sourcing
2. Machine names are byte-identical except the intended rename. 3. Dependency is clean. Still open: whether |
loop-security: PASSAudited head: No security defect in this diff. It is a pure name/number re-sourcing with no new logic, no new Cleared1. No numeric re-mapping — the main risk, and it is absent. Sourcing 2. The rename fails closed, and breaks no known consumer. 3. No new leakage. 4. Dependency is clean. Exactly ONE 5. No new panics on a peer-reachable path. Zero 6. The guard is not vacuous. 7. Non-gating — LOW, quality, hand to the correctness gate
In Rust that is an actual newline character plus the spaces, not a line continuation (a continuation Not a security finding and I am not gating on it: Scope I did not coverI did not compile or run the suite — the diff introduces no logic and CI is green on this exact head. |
MichaelTaylor3d
left a comment
There was a problem hiding this comment.
loop-reviewer correctness gate on head 375cf44 — one GATING finding, inline. Everything else in the diff checks out; see the interim comment for per-item evidence.
loop-reviewer — VERDICT: CHANGES-REQUIREDAudited head: One gating finding, posted inline on Per-item evidence:
Blast radius measured with ripgrep + direct reads — the gitnexus dig-node index is ~300 commits stale Re-gate scope when the finding lands: the one-line literal only. No other leg needs re-running. |
…rift # Conflicts: # Cargo.lock # Cargo.toml
…rift # Conflicts: # Cargo.lock # Cargo.toml
…rift # Conflicts: # Cargo.lock # Cargo.toml
Scoped re-gate IN PROGRESS — not the verdicthead read: Confirmed so far:
Note on provenance, non-gating: the fix and the bump were applied inside merge-commit conflict resolutions ( Remaining: confirming the two new tests actually run green locally. Verdict follows. |
VERDICT: PASS (scoped re-gate)head read: Scope of this pass, per §1.10: the round-1 gating finding, the delta since 1. The delta is only the fix, the merges, and the bump
Everything else in 2. The gating finding is genuinely fixed, and a test discriminates
Two tests, and both would fail under the defect (a literal
Ran locally in a detached worktree at this head: Not done, and stated rather than implied: I did not perform a revert-proof (restoring the old literal and watching it go red) — that is an 11-minute rebuild for a property readable from the assertions themselves, since a literal newline is 3. Version gate
Non-gating noteThe fix and the bump were applied inside merge-commit conflict resolutions ( Merge remains the orchestrator's, and this PR is still a draft. |
origin/main advanced to b9979d8 (#494, the shell error catalogue). Only the workspace version and Cargo.lock conflicted; #494 touches no file this branch does. The pre-assigned 0.248.0 is kept and the lock re-resolved from main's. Subject is `chore:` and not `merge:` deliberately: `merge` is not in this repo's commitlint type-enum, and the three earlier merge commits on this branch were rewritten for the same reason. Co-Authored-By: Claude <noreply@anthropic.com>
…0.250.0 Main moved to 0.246.0 while this branch was being fixed. Same two conflicts as the previous merge and the same resolution: Cargo.toml keeps only the assigned 0.250.0 (every other hunk of main verbatim), Cargo.lock taken from origin/main then `cargo update -w --offline`, which relocked one package. No source conflicts; SPEC.md auto-merged. Co-Authored-By: Claude <noreply@anthropic.com>
Closes #478
What changed
dig-node-service'sErrorCodenow SOURCES its number and machine string fromdig_rpc_protocol::ErrorCodefor every code the two share, instead of restating them. Thisextends the pattern already used in the same file for three wallet codes.
-32004isRESOURCE_UNAVAILABLEeverywhere: the enum variant is renamed toResourceUnavailableand the hand-written arms incode()/name()are gone.originbecomesnode, notupstream— see below.-32700,-32600,-32601,-32602,-32010,-32030,-32031,-32032.-32060 PEER_PING_REFUSEDuntouched, per the issue.The issue's premise, re-measured — and why this needs no cascade
The issue expected a released-wire-name collision requiring an alias in
dig-rpc-protocol.Measured on
origin/main, that is not the situation:RESOURCE_NOT_AVAILABLE_AT_ROOThas zero producers and zero consumers. Every-32004framedig-node emits is minted in
dig-node-coreand framed byseams/dig_rpc/errors.rs::error_object,which derives
data.codefromdig_rpc_protocol::ErrorCode— so it has always carriedRESOURCE_UNAVAILABLE. The long name existed only inmeta.rsand in a test that pinned it.RESOURCE_UNAVAILABLE(dig-dns, dig-sdk); docs.dig.net alreadypublishes
RESOURCE_UNAVAILABLE.So this was a discovery-document lie, not a wire break: a client generated from
rpc.discoverwould
match "RESOURCE_NOT_AVAILABLE_AT_ROOT"and never match anything. Real under §6.2 — thecatalogue is a contract — but no live client is affected, and no
dig-rpc-protocolrelease and norelease-first cascade is required. The two names denote the same condition (the crate's own
description for
ResourceUnavailableis literally "Resource not available at the requested root"),and the layer distinction is already carried by the separate
data.originfield.No alias and no compatibility period: an alias would add public surface for a name with no producers
and no consumers, institutionalising the drift.
SYSTEM.md's 0.9.0-yank precedent governs names thatactually shipped on the wire; this one never did.
The
originfixThe catalogue claimed
-32004hasorigin: "upstream", but the node library mints-32004locallyon an ordinary miss (
dig.fetchRange"resource not held",dig.getManifest"capsule not heldlocally"), and
SPEC.mdalready admitted both. Unlike the name,data.originIS on the wire and ISderived per-frame by the minter — so the catalogue value is the default a client should expect from
this node, and it may not say
upstreamfor a code this node mints itself. Set tonode; theper-frame value stays authoritative, and the SPEC row now says so.
DispatchFailed/-32000— EXCLUDED, and filed rather than renamedJudged fresh rather than swept in, and it is the opposite case to
-32004:DISPATCH_FAILEDis on the wire —rpc.rs:67-77putscode.name()intoerror.data.code, andserver.rsmintsErrorCode::DispatchFailedat two sites.dig-node-coremints no-32000underServerError(grep returns nothing), so unlike-32004there is no second name reaching the same client. The shell's catalogue and the shell's frames agree.
Renaming it to the crate's generic
SERVER_ERRORwould therefore be a genuine released-wire-namechange of exactly the class the
dig-rpc-protocol0.9.0 yank records. Left alone, excluded from thesourcing with a comment at both
code()andname()explaining why, and split out as #496.Blast radius
gitnexus's dig-node index is ~301 commits stale and returns a false-safe
impactedCount: 0, so thiswas measured with ripgrep + direct reads, stated per §2.0's fallback clause.
ResourceNotAvailableAtRootoccurred in exactly two files —crates/dig-node-service/src/meta.rs(6 sites) and
tests/openrpc_drift_guard.rs— plus one doc comment indig-node-core/src/lib.rs:240and four
SPEC.mdpassages. All are in this diff; a repo-wide grep for the old name now returns onlythe two deliberate mentions in the inverted test's own prose. Nothing outside dig-node referenced it.
Tests
crates/dig-node-service/tests/openrpc_drift_guard.rs:shell_error_names_match_the_shared_catalogue— the INVARIANT, not a list: for every variant inmeta::ErrorCode::all()whose numberdig_rpc_protocol::ErrorCode::ALLalso declares, the shell's.name()must equal the crate'smachine_code(). It also asserts it checked at least 7 codes, so afuture change that empties the intersection cannot make it pass vacuously.
DispatchFailedis theone documented exclusion.
the_catalogued_name_for_32004_is_the_name_the_node_emits— the EMITTED FRAME, not thecatalogue: drives a real
-32004out ofhandle_rpcon an empty ephemeral node (hermetic, nonetwork) and asserts
error.data.code == "RESOURCE_UNAVAILABLE", then asserts the catalogue entryfor
-32004carries that same string. Comparing the two artefacts is what makes it a decision testrather than a presence test.
reconciled_error_codes_are_catalogued_with_correct_originwas inverted — it pinned the defect.Recorded pre-fix failure (tests written and run BEFORE the
meta.rschange):Both failed on the real defect, and the second one is the measurement that establishes the frame
carries
RESOURCE_UNAVAILABLEtoday.After:
0 filtered outin each — the assertions ran rather than being filtered away.A full
cargo test -p dig-node-service(all integration targets) could not be completed on this host:it fails during LINKING with
link.exe … 0xc000012dand a run of rustc ICEs, on a 19 GB target treewith several sibling lanes building concurrently. That is a host-resource failure, not a compile error
in this diff — the same tree builds and passes when targets are built individually. CI is the honest
measurement of the remaining targets.
Docs / SPEC
SPEC.md:98,:970,:1183,:3197— the "differs from the contract crate" hedges fix(rpc): mint error frames from the taxonomy so data.code and data.origin are present #477 wasforced to write are gone; the error-table row reads
RESOURCE_UNAVAILABLE/node, and the oneremaining shell-specific string (
DISPATCH_FAILED) is stated with a pointer to decide: -32000 is DISPATCH_FAILED in the shell and SERVER_ERROR in the contract crate #496.RESOURCE_UNAVAILABLE; zero occurrencesof
RESOURCE_NOT_AVAILABLE_AT_ROOTanywhere in the tree. Verified rather than skipped (§4.3).Version
0.235.0 → 0.237.0. Minor: the published discovery document changes a machine name and an origin
value, which is a compatible extension for a name nothing emitted, but not a silent patch. 0.236.0 is
claimed by a sibling lane.