Task
Adopt dig-node-control-interface 0.22.0 and implement control.spends.list — the sanctioned
reader for the automated-spend audit record.
Parent epic: https://github.com/DIG-Network/dig_ecosystem/issues/3166
Contract: DIG-Network/dig-node-control-interface#30 (merged c9c8bf8c, published 0.22.0)
Consumer waiting on it: DIG-Network/dig-app#289 (PR #290, already coded against the method)
Why this ticket exists — the contract is published, nothing serves it
Measured on main today:
dig-node-service/Cargo.toml:92 and dig-wallet/Cargo.toml:53 both declare dig-node-control-interface = "0.21".
spends.list / spends_list appears nowhere in crates/.
So a release watcher reporting the crate "live" is reporting the contract, not the capability. §1.3b:
a contract crate is not done when it publishes; it is done when every consumer has adopted it. dig-app
PR#290 calls control.spends.list and receives METHOD_NOT_FOUND from every node until this lands.
What the implementation needs, beyond the dispatch arm
The PR#31 gate measured that this is not merely wiring an existing query to a new method name:
SpendQuery carries no after_id. The declared method is paginated by cursor; the existing query
type cannot express where to resume.
SpendLog::query cannot report complete. The contract distinguishes "that is all of them" from
"we stopped here", and the current query has no way to say which.
Both must be extended, along with their callers. Budget for that rather than discovering it mid-lane.
The shape is already fixed by the published contract — match it exactly
The catalog was verified field-by-field against this repo's shipped spend_audit.rs
(SpendRecord, SpendStatus, FailureStage, Asset, Authority), and the declared ordering is
exactly what spend_audit.rs:539 implements. Do not re-derive the shape; read 0.22.0 and conform.
Two properties in that contract are load-bearing and must survive into the implementation:
- The failure-stage distinction.
Signing definitively did not spend; Broadcast and
Confirmation mean a signed bundle went out and money may have moved. That distinction has been
collapsed and re-fixed twice in this repo and once in dig-app. Use
FailureStage::money_may_have_moved(); do not re-list the variants anywhere.
- An unresolved outcome is a first-class state, not an error. The response must be able to say
"signed, and we do not know if it landed".
Why the accuracy bar is higher than a normal read method
This method is the compensating control for a §908 carve-out: the node signs mirror-coin spends
without per-spend user approval, at the user's explicit instruction. The audit record is what stands
in for consent. A reader that misreports those spends weakens the only thing substituting for it.
Also
- Bounding. The audit log grows without limit. Honour the contract's cursor and its
complete
signal — and if a response is truncated, it must say so. A caller cannot distinguish "no more
spends" from "we stopped telling you" unless that is explicit.
- Read-only. Never triggers a spend, never signs, never mutates.
- §2.4b: bring
dig-*/chia-* deps to latest in the same PR; chia-* move as a SET. Index checks need
a User-Agent header or the registry reads as unpublished.
SPEC.md (§4.2) and the #426 CLI/RPC parity test kept green.
Acceptance
dign spends and dig-app's Activity tab read the same records through this method and agree. Evidence
is that agreement on a real machine (§2.6) — two surfaces reading one source and disagreeing is the
defect this exists to prevent.
Task
Adopt
dig-node-control-interface0.22.0 and implementcontrol.spends.list— the sanctionedreader for the automated-spend audit record.
Parent epic: https://github.com/DIG-Network/dig_ecosystem/issues/3166
Contract: DIG-Network/dig-node-control-interface#30 (merged
c9c8bf8c, published 0.22.0)Consumer waiting on it: DIG-Network/dig-app#289 (PR #290, already coded against the method)
Why this ticket exists — the contract is published, nothing serves it
Measured on
maintoday:dig-node-service/Cargo.toml:92anddig-wallet/Cargo.toml:53both declaredig-node-control-interface = "0.21".spends.list/spends_listappears nowhere incrates/.So a release watcher reporting the crate "live" is reporting the contract, not the capability. §1.3b:
a contract crate is not done when it publishes; it is done when every consumer has adopted it. dig-app
PR#290 calls
control.spends.listand receivesMETHOD_NOT_FOUNDfrom every node until this lands.What the implementation needs, beyond the dispatch arm
The PR#31 gate measured that this is not merely wiring an existing query to a new method name:
SpendQuerycarries noafter_id. The declared method is paginated by cursor; the existing querytype cannot express where to resume.
SpendLog::querycannot reportcomplete. The contract distinguishes "that is all of them" from"we stopped here", and the current query has no way to say which.
Both must be extended, along with their callers. Budget for that rather than discovering it mid-lane.
The shape is already fixed by the published contract — match it exactly
The catalog was verified field-by-field against this repo's shipped
spend_audit.rs(
SpendRecord,SpendStatus,FailureStage,Asset,Authority), and the declared ordering isexactly what
spend_audit.rs:539implements. Do not re-derive the shape; read 0.22.0 and conform.Two properties in that contract are load-bearing and must survive into the implementation:
Signingdefinitively did not spend;BroadcastandConfirmationmean a signed bundle went out and money may have moved. That distinction has beencollapsed and re-fixed twice in this repo and once in dig-app. Use
FailureStage::money_may_have_moved(); do not re-list the variants anywhere."signed, and we do not know if it landed".
Why the accuracy bar is higher than a normal read method
This method is the compensating control for a §908 carve-out: the node signs mirror-coin spends
without per-spend user approval, at the user's explicit instruction. The audit record is what stands
in for consent. A reader that misreports those spends weakens the only thing substituting for it.
Also
completesignal — and if a response is truncated, it must say so. A caller cannot distinguish "no more
spends" from "we stopped telling you" unless that is explicit.
dig-*/chia-*deps to latest in the same PR;chia-*move as a SET. Index checks needa
User-Agentheader or the registry reads as unpublished.SPEC.md(§4.2) and the #426 CLI/RPC parity test kept green.Acceptance
dign spendsand dig-app's Activity tab read the same records through this method and agree. Evidenceis that agreement on a real machine (§2.6) — two surfaces reading one source and disagreeing is the
defect this exists to prevent.