Task
Add control.spends.list (and whatever the Activity tab needs alongside it) to dig-node-control-interface, and publish it — so dig-app can read the automated-spend audit record.
Why this is its own ticket
The record and its dign CLI landed in DIG-Network/dig-node#378. The control-interface method was deliberately left out, and the reasoning is right: the interface is a published crate, so §4.1 release-first applies — the method must exist in a published version before dig-app can adopt it. Adding it to KNOWN_UNPUBLISHED would grow exactly the drift that list exists to shrink.
This is the last link between the record and DIG-Network/dig-app#289's Activity tab. Until it publishes, the tab has nothing to read.
The architecture this preserves
dig-node -> OWNS the record (source of truth)
├── dign CLI reads it locally, no node contact
└── dig-app Activity reads it over THIS interface
One record, two views — never two records that must agree. The reader is already shared, so this is a dispatch arm rather than a second implementation. Do not reimplement the read path here.
What it must carry
Enough for the Activity tab to be honest without re-deriving anything:
- the spend's kind, purpose, asset, amount, fee, store, timestamps
- status including its evidence — the record models
Confirmed { height, coin_id } with the evidence inside the variant, so a confirmation height cannot exist without a confirmation. Preserve that shape across the wire; flattening it into a nullable height plus a status string is exactly how the guarantee gets lost in transit.
Unresolved distinct from Failed — "signed and don't know" is not "didn't happen", and a UI that shows them alike is lying about money.
- the funding coin ids and the intended target coin id, kept distinct — they are separate types in the record precisely because the legacy confused them and waited on the wrong one.
unreadable_lines, so a truncated audit trail cannot present as a complete one.
Filtering
The CLI filters by time range, store, kind and status. The tab will want the same; put the filtering in the method rather than shipping everything and filtering client-side, or the tab's behaviour will drift from the CLI's.
Evidence
A round-trip test showing a Confirmed entry keeps its height and coin id, and that Unresolved does not deserialise as Failed. Plus the published version confirmed from the crates.io index — the User-Agent header is required, and four repos this week produced green release runs that published nothing.
Related
Task
Add
control.spends.list(and whatever the Activity tab needs alongside it) todig-node-control-interface, and publish it — so dig-app can read the automated-spend audit record.Why this is its own ticket
The record and its
dignCLI landed in DIG-Network/dig-node#378. The control-interface method was deliberately left out, and the reasoning is right: the interface is a published crate, so §4.1 release-first applies — the method must exist in a published version before dig-app can adopt it. Adding it toKNOWN_UNPUBLISHEDwould grow exactly the drift that list exists to shrink.This is the last link between the record and DIG-Network/dig-app#289's Activity tab. Until it publishes, the tab has nothing to read.
The architecture this preserves
One record, two views — never two records that must agree. The reader is already shared, so this is a dispatch arm rather than a second implementation. Do not reimplement the read path here.
What it must carry
Enough for the Activity tab to be honest without re-deriving anything:
Confirmed { height, coin_id }with the evidence inside the variant, so a confirmation height cannot exist without a confirmation. Preserve that shape across the wire; flattening it into a nullable height plus a status string is exactly how the guarantee gets lost in transit.Unresolveddistinct fromFailed— "signed and don't know" is not "didn't happen", and a UI that shows them alike is lying about money.unreadable_lines, so a truncated audit trail cannot present as a complete one.Filtering
The CLI filters by time range, store, kind and status. The tab will want the same; put the filtering in the method rather than shipping everything and filtering client-side, or the tab's behaviour will drift from the CLI's.
Evidence
A round-trip test showing a
Confirmedentry keeps its height and coin id, and thatUnresolveddoes not deserialise asFailed. Plus the published version confirmed from the crates.io index — theUser-Agentheader is required, and four repos this week produced green release runs that published nothing.Related