Files
routstrd/docs/wallet-mint-recovery.md

72 lines
3.4 KiB
Markdown

# Mint quote recovery: scope and troubleshooting
`routstrd wallet recover` explicitly retries mint operations through coco using
**their existing stored outputs**. It can restore signatures when a quote is
already issued, and reopen failed operations when explicitly requested:
```sh
routstrd history --json
routstrd wallet recover --op <operationId> --include-failed
```
Failed operations require explicit IDs over both HTTP and the CLI. A successful
re-run on an already finalized operation is a no-op. Requests that exceed their
wait budget are not cancelled; explicit retries skip the operation while the
underlying work is outstanding.
## What this fixes—and what it does not
Coco already checks pending quotes on startup and the daemon periodically
refreshes them. A quote paid while the daemon was offline does not, by itself,
require a new issuance implementation.
This change makes normal cleanup confirm UNPAID with the mint before failing an
expired quote. PAID, ISSUED and unverified quotes remain pending. It also gives
operators a recovery path for operations previously marked failed.
It does **not** replace rejected outputs with fresh outputs on an active keyset.
An inactive-keyset rejection can therefore remain retryable with zero recovery.
Recovery reports coco's persisted mint error when available, rather than only a
generic “remains pending” error.
Do not infer that the production incidents were caused by keyset retirement.
Before claiming those incidents are fixed, collect:
- The affected operation IDs, quote IDs, state and persisted `error`.
- A fresh remote quote state and, where provided, paid/issued amounts.
- The keyset IDs in the stored outputs and the mint's current keyset metadata.
- A reproduction showing existing recovery fails and the proposed fix succeeds.
Inspect persisted operation data through a read-only database copy; do not edit
rows or run recovery scripts concurrently with a daemon against the same wallet.
Never share the mnemonic, output secrets, or full wallet database in a PR.
A future fresh-output path must preserve original outputs for uncertain issuance
and NUT-09 restore, allocate fresh deterministic counters safely, and coordinate
with coco's watcher/processor. It needs its own integration tests before handling
real funds.
## Cleanup preview and force
`wallet cleanup --dry-run` is local-only: it reports `mintQuoteCandidates`, not
confirmed failures. `failedMintQuotes` and `leftForRecovery` are zero because no
mint check or cleanup transition was performed. Send/melt counts remain planned
cleanup counts in dry-run mode.
`--force` deliberately bypasses mint confirmation and can strand paid sats in a
failed operation. Prefer normal cleanup. Forced operations can be retried with
`--op <operationId> --include-failed`, but recovery still depends on the mint
accepting their stored outputs or restoring their signatures.
## Integration and release notes
The reopen helper uses private coco-core 1.0.1 methods. Retain real-Manager and
HTTP fake-mint coverage, use frozen dependency installs, and re-run integration
tests on coco upgrades. A controlled low-value live-mint smoke test remains
recommended before release.
PR #118 removes `cocod-client.ts`. When integrating that change, move recovery
and cleanup contracts into its replacement `wallet-client.ts`, rename HTTP error
references accordingly, and make recovery mandatory for the in-process client.
This follow-up does not pull in #118's unrelated removal.