Skip to content

feat(custody): freeze node-side USER custody for removal (step 1 of #1701) - #321

Merged
MichaelTaylor3d merged 8 commits into
mainfrom
loop/1701-freeze-custody
Aug 23, 2026
Merged

feat(custody): freeze node-side USER custody for removal (step 1 of #1701)#321
MichaelTaylor3d merged 8 commits into
mainfrom
loop/1701-freeze-custody

Conversation

@MichaelTaylor3d

@MichaelTaylor3dMichaelTaylor3d commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Step 1 (FREEZE) of https://github.com/DIG-Network/dig_ecosystem/issues/1701.

Closes#320

🔴 Nothing is deleted and no keystore blob is touched

Every deleted line in this diff is a version string or a SPEC.md line extended in place:

$ git diff origin/main...HEAD | grep '^-[^-]'
-version = "0.141.0"
-version = "0.29.1"
-18.20. **Node-custodied MULTI-wallet provisioning + custody lifecycle (#370/#427).** For the thin-client

No code is removed, no dependency dropped, no served method withdrawn. The population count came back
ZERO on all four machines, so removal is unblocked — but removal is step 4 and is deliberately not here
(see below).

What is frozen

#[deprecated], each carrying the same note pointing at the #1500 ratification:

SymbolFile
wallet_authz::AUTH_PREFIXcrates/dig-node-service/src/wallet_authz.rs
UnlockAuth::unlock, UnlockAuth::sign_unlockcrates/dig-wallet/src/sage/auth.rs
WalletCustody::create / import / restorecrates/dig-wallet/src/sage/custody.rs
WalletCustody::reveal_mnemonic / sign_oncecrates/dig-wallet/src/sage/custody.rs

Module docs on auth.rs, custody.rs and wallet_authz.rs, plus SPEC.md §7.12 / §18.20 / §18.24,
name the ratification (2026-07-22T03:27:48Z) and state that dig-account's PolicyAuthorizer is the
only enforcing custody gate from here.

OpenRPC discovery — the ticket's premise, corrected

The surface was already absent from discovery: meta::methods() carries 63 methods and none is
under auth. or wallet., and the Sage plane that dispatches auth.* (POST /:method) has no runtime
discovery at all. So this PR removes no entry. It adds the guard that keeps the absence true, which is
the part a future change could silently undo — and the guard, not a deletion, is the reviewable artifact.

the_frozen_custody_surface_is_absent_from_every_discovery_artifact reads method names out of four
layers: the methods() catalogue, public_method_names() (the rpc.dig.net-facing view), the rendered
OpenRPC document, and the rendered well-known document. It asserts each layer discloses at least one
name first, so a layer the guard cannot see fails loudly instead of passing vacuously.

Mutation proof — two placements, because one would not have been enough

A guard that only inspected methods() would stay green if someone spliced a method object straight
into the OpenRPC body. Both were mutated separately:

  1. Catalogue layer — added a MethodInfo { name: "auth.status", .. } beside rpc.discover:

    meta::tests::the_frozen_custody_surface_is_absent_from_every_discovery_artifact ... FAILED
    meta::methods() catalogue discloses auth.status, under the frozen auth.*namespace

  2. OpenRPC layer only, catalogue untouched — pushed {"name":"auth.status"} onto method_objs:

    meta::tests::the_frozen_custody_surface_is_absent_from_every_discovery_artifact ... FAILED
    the OpenRPC document discloses auth.status, under the frozen auth.*namespace

The message names the layer, so the failure says which door was opened. Both mutations were reverted
from a committed baseline via a file copy, never git checkout.

the_freeze_guard_leaves_the_control_plane_wallet_chain_reads_discoverable pins the other side: the
frozen prefixes are bare (wallet.), while the light-client chain reads are control.wallet.*. Its
haystack is the production control::CONTROL_METHODS list, not a literal, and it asserts it found at
least two so it cannot pass vacuously.

Still functional

the_frozen_custody_surface_is_still_functional_end_to_end walks the whole key-touching path —
import -> unlock -> sign_once -> reveal_mnemonic -> byte-for-byte seed match -> a wrong password
still fails closed. Named honestly: the freeze introduces no behaviour change to revert, so this is a
forward guard against step 4 breaking custody, not a revert-proof of a fix.

wallet_authz::tests::auth_methods_are_gated_and_no_token_is_denied (pre-existing) is load-bearing for
this PR specifically: the #[allow(deprecated)] had to move onto classify itself, since an attribute
on a tail if expression is not stable Rust, and that test is what proves the gate did not weaken.

Two deliberate non-changes

seed_store.rs is NOT #[deprecated]. It is a shared at-rest primitive with a second, unaffected
caller — the node's OWN operator identity (autoseed.rs, the DIGOP1/DIGVK1 blobs), which no
ratification retires. Deprecating it would mark live code as retired. It carries a doc note saying that
instead.

Step 4 is not folded in. The ticket's wording is "drop dig-wallet from dig-node-service", and
that predates the light client. control.rs holds 56 dig_wallet references serving the
control.wallet.* chain reads, and WalletCustody is fused into sync_supervisor as the node's own
watched-address source. Removal is a carve-out of the custody subset from a crate the node still needs,
and doing it inside a freeze PR would put the top-priority light client behind a diff nobody could
review as one thing.

Blast radius checked

gitnexus impact was not used — no per-worktree index was built for this lane. The fallback was
ripgrep call-graph enumeration plus cargo check --all-targets, which for a pure #[deprecated] change
is exact rather than approximate: the compiler enumerates every use site by definition. Ten sites
warned. Nine are test code; the single production site is WalletCustody::restore delegating to the
frozen import. Each took the narrowest #[allow(deprecated)] available, with a comment naming #1701.
The lint was not widened anywhere and no attribute was dropped.

Risk: LOW. Additive attributes and docs, no control-flow change, no removal.

No crates/dig-node-core/ file is touched — that crate belongs to the sibling capsule-warm lane.

Verification

  • cargo test --workspace --no-fail-fast on the MERGED tree — 2312 passed, 0 failed, 5 ignored,
    41 suites
    , exit 0, zero FAILED lines and zero error: lines in the log
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo fmt --all --check — clean
  • Resolved names, not a bare ok:
    • meta::tests::the_frozen_custody_surface_is_absent_from_every_discovery_artifact ... ok
    • meta::tests::the_freeze_guard_leaves_the_control_plane_wallet_chain_reads_discoverable ... ok
    • sage::custody::tests::the_frozen_custody_surface_is_still_functional_end_to_end ... ok

Version

0.141.0 -> 0.142.0 -> 0.143.0 (root workspace), dig-wallet0.29.1 -> 0.30.0. Minor,
not major
: #[deprecated] is an additive signal and nothing is removed or renamed, so no consumer
breaks.

The version collision happened and was handled.origin/main read 0.141.0 at bump time, so this
branch took 0.142.0. While CI ran, #319 merged and chore(release): v0.142.0 landed, taking that
number. main was merged in and the bump re-taken to 0.143.0. The union was then actually
compiled
cargo clippy --workspace --all-targets -- -D warnings clean and the full suite re-run —
rather than assumed green from two separately-green branches.

Deferred, and said out loud

§2.4b (touch a crate -> bring its dig-*/chia-* deps to latest) is not done here. These are
path-internal crates in an apps repo, and a chia uplift inside a freeze PR would dwarf the change and
put the light client at risk — §2.4b's own split clause. Flagged rather than silently skipped.

MichaelTaylor3dand others added 2 commits August 23, 2026 07:03
Step 1 of dig_ecosystem#1701. Deprecate the auth.*/custody entry points
and document the #1500 ratification; delete nothing.
Co-Authored-By: Claude <noreply@anthropic.com>
Comment threadcrates/dig-wallet/src/sage/custody.rs Fixed
Also bumps the release version to 0.142.0 (minor: deprecation is
additive, nothing removed).
Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3dMichaelTaylor3d changed the title feat(custody)!: freeze node-side USER custody for removal (step 1 of #1701)feat(custody): freeze node-side USER custody for removal (step 1 of #1701)Aug 23, 2026
@MichaelTaylor3d
MichaelTaylor3d marked this pull request as ready for review August 23, 2026 15:20
@MichaelTaylor3d
MichaelTaylor3d merged commit 2ce8002 into mainAug 23, 2026
16 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the loop/1701-freeze-custody branch August 23, 2026 15:20
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

freeze node-side USER custody: deprecate the auth.*/custody surface and guard it out of discovery

2 participants

@MichaelTaylor3d@github-advanced-security