Skip to content

feat(cli): dig-store store-status subcommand (#1349)#30

Merged
MichaelTaylor3d merged 2 commits into
mainfrom
feat/store-status-subcommand
Jul 21, 2026
Merged

feat(cli): dig-store store-status subcommand (#1349)#30
MichaelTaylor3d merged 2 commits into
mainfrom
feat/store-status-subcommand

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

Closes #1349.

What

Adds a new dig-store store-status <store_id> [--json] [--confirmation-target N] [--coinset-url URL] subcommand that reports a store's aggregate on-chain status by composing the NC-9 fail-closed dig_store::get_store_status (dig-store 0.5.0) — a thin consumer, NOT a re-implementation. Distinct from the existing working-tree status command (no overload).

Integration approach (Option B, orchestrator-approved)

digs has no dig_chainsource_interface::ChainSource today (its chain access is digstore-chain::ChainReads/Coinset + a separate digstore-prover::ChainSource). A small coinset-backed adapter wraps digs' existing hardened Coinset (retry/timeout #84) as a dig_chainsource_interface::ChainSource, implementing only the 3 methods get_store_status exercises (coin_spend, coin_record, peak_height); the other 4 fail closed with Unsupported. The money-critical lineage walk lives inside dig-store (already triple-gated).

§5.3 ruling

store-status is a raw Chia-chain read, NOT a dig-node content read, so it does NOT use the dig.local/localhost/rpc.dig.net content ladder. It reads via coinset with a user-facing custom-endpoint override: --coinset-url / $DIG_COINSET_URL.

Follow-ups (NOT chased here)

  • Converge digs' chain reads onto chia-query's provider registry once a lightweight (no-peer-handshake) coinset provider exists.
  • head_signature is always None (library gap, #1348).

Status

WIP / draft — do not merge. Implementation + tests landing next.

Blast radius

gitnexus DISABLED; scoped via ripgrep + read. New subcommand = additive: new Command::StoreStatus variant + a new command module + a new adapter module; touches cli.rs (enum + args), commands/mod.rs (dispatch), CLI Cargo.toml (2 new deps). No existing symbol edited.

WIP stub: establishes the branch for the `dig-store store-status <store_id>`
subcommand consuming dig-store 0.5.0 get_store_status via a small coinset-backed
dig_chainsource_interface::ChainSource adapter. Implementation follows.
…_status (#1349)

Add `dig-store store-status <store_id> [--json] [--confirmation-target N]
[--coinset-url URL]`, reporting a store's aggregate ON-CHAIN status (live/
melted/not-found, confirmations, live root, owner puzzle hash, program hash,
head signature, coin id, verified, generations).

The CLI is a THIN consumer of the fail-closed `dig_store::get_store_status`
(dig-store 0.5.0, NC-9, already triple-gated) — it never re-implements the
lineage walk. A small coinset-backed adapter presents digs' existing hardened
`digstore_chain::coinset::Coinset` transport as the canonical
`dig_chainsource_interface::ChainSource`, implementing only the three reads the
aggregator exercises (coin_spend, coin_record, peak_height) and failing closed
(Err, never a false absence) on the rest.

Store status is a raw Chia-chain read, not a dig-node content read, so it does
NOT use the dig-node content ladder; the endpoint resolves as
--coinset-url > $DIG_COINSET_URL > the default coinset.org URL, giving the user
a first-class custom-endpoint override for this surface.

Bumps the workspace 0.17.2 -> 0.18.0 (additive minor: a new subcommand).

Tests: adapter transport-mapping + fail-closed (None vs Err) + off-path
Unsupported; store-id parsing (hex / 0x / URN); coinset-url resolution;
Live/Melted/NotFound rendering + --json shape; and end-to-end NotFound +
fail-closed through the library against the canonical MockChainSource.
@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

Implementation complete — CI running (HEAD 6aa3a0d).

DONE

  • Adapter crates/digstore-cli/src/ops/coinset_chain_source.rs: CoinsetChainSource<C: ChainReads> presents digs' Coinset as dig_chainsource_interface::ChainSource; implements coin_spend/coin_record/peak_height (fail-closed None vs Err), other 4 methods return Unsupported. CoinInfo -> CoinRecord mapping with zero-height/timestamp sentinels -> None.
  • Subcommand crates/digstore-cli/src/commands/store_status.rs: store-status <store_id> [--json] [--confirmation-target N] [--coinset-url URL], distinct from working-tree status; consumes dig_store::get_store_status; human table + --json (StoreStatus serializes directly). Endpoint = --coinset-url > $DIG_COINSET_URL > default coinset.org (§5.3 ruling: raw chain read, not the node ladder).
  • Deps: dig-store = "0.5" + dig-chainsource-interface = "0.1" (+ dev-dep testing feature). Version 0.17.2 -> 0.18.0.
  • 22 new tests (adapter mapping/fail-closed, store-id parse, url resolution, Live/Melted/NotFound render + JSON shape, end-to-end NotFound + fail-closed via MockChainSource).

Local gate GREEN: cargo fmt --all --check, cargo clippy -p digstore-cli --all-targets --locked -D warnings, cargo test -p digstore-cli --locked (all unit + integration pass), cargo deny check advisories bans sources.

Post-merge (§3.5): dig-store CLI reinstall + integration test against the installed binary (--force --locked); guest-wasm build prereq (cargo build -p digstore-guest --target wasm32-unknown-unknown --release) needed on a clean checkout.

NEXT: watch CI to green; hand to scoped gate (reviewer + light security on the adapter fail-closed mapping + endpoint resolution). Do NOT merge (orchestrator gates).

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

CI fully GREEN at HEAD 6aa3a0d — all 10 checks pass (build & test ubuntu + windows, Analyze rust/actions/js, CodeQL, commitlint, version-increment, supply-chain audit, dig-client-wasm). Ready for the scoped gate (reviewer + light security on the adapter fail-closed mapping + endpoint resolution). Not marking ready / not merging — orchestrator gates + merges.

@MichaelTaylor3d MichaelTaylor3d left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scoped correctness review (fresh context) — VERDICT: PASS

Re-run of the gate leg that died to a session cap. Reviewed the CLI + adapter wiring only; the dig_store::get_store_status lineage logic (NC-9, triple-gated in the library) was NOT re-reviewed, per scope.

Verified

  • Option B adapter is a thin transport bridge (crates/digstore-cli/src/ops/coinset_chain_source.rs): CoinsetChainSource<C: ChainReads> implements dig_chainsource_interface::ChainSource by mapping digs' existing hardened Coinset/ChainReads. Only the 3 methods get_store_status exercises are real (coin_record, coin_spend, peak_height); the other 4 fail closed with ChainSourceError::Unsupported. No lineage/Live-Melted decision is re-implemented in the CLI/adapter — it composes the library aggregator.
  • Fail-closed contract preserved: every ChainReads error maps to ChainSourceError::Transport, never a false Ok(None); unknown coin and unspent-tip both correctly yield Ok(None) (coin_spend.rs:754-774). Well covered by adapter tests + the end-to-end transport_failure_fails_closed_not_absent test through the real library + MockChainSource.
  • block_on safety: digstore_cli::run() (lib.rs:42) is a plain sync entrypoint (no #[tokio::main]), so the adapter's owned current-thread runtime driving block_on never nests inside an ambient runtime. The module doc claim holds.
  • Subcommand distinct from status: Command::StoreStatus registered as store-status (cli.rs:221), no overload of the working-tree status; human table renders all StoreStatus fields with - for None; --json emits StoreStatus directly. Dispatch is consistent (early no-workspace return + listed in the unreachable!("handled above") arm).
  • §5.3 ruling honored: raw Chia-chain read via coinset with --coinset-url > $DIG_COINSET_URL > digstore_chain::config::DEFAULT_COINSET_URL (store_status.rs:381-391); NOT the dig-node content ladder; no hardcoded coinset URL as the only path.
  • Deps: dig-store="0.5" + dig-chainsource-interface="0.1" from crates.io, no git=. Single chia-sdk tree (chia-protocol 0.26, chia-wallet-sdk 0.30, chia-sdk-driver 0.30 — no dups).
  • dig-constants check: (1) nothing here belongs in dig-constants — the coinset default already lives in digstore_chain::config, confirmation-target comes from dig_store::DEFAULT_CONFIRMATION_TARGET; store-id parsing is local input handling, not a shared value. (2) no hardcoded literal here duplicates a dig-constants-published value. Clear.
  • Tests: 22 new tests (10 adapter + 11 command + 1 cli-parse). All CI green on ubuntu + windows; CodeQL/GHAS/supply-chain/version-increment/commitlint all pass.
  • readable-code §2.5: intent-revealing names, WHY-comments, doc-comments on public items, small pure human_rows/status_label. No sage refs. Honors digs' CONTRIBUTING (no Co-Authored-By).
  • SemVer: 0.17.2 → 0.18.0 minor (additive new capability). Correct.

Non-gating notes (not blockers)

  • PR is a draft and the body still reads "WIP / draft — do not merge" though implementation + tests have landed and CI is green. Orchestrator should mark ready-for-review + refresh the body before merge.
  • head_signature always None is a known library gap (#1348), correctly surfaced as -; out of scope here.

No CHANGES-REQUIRED findings.

@MichaelTaylor3d
MichaelTaylor3d marked this pull request as ready for review July 21, 2026 01:04
@MichaelTaylor3d
MichaelTaylor3d merged commit 996ffb2 into main Jul 21, 2026
10 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the feat/store-status-subcommand branch July 21, 2026 01:04
Sign up for free to 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.

1 participant