Skip to main content

Crate btctax_cli

Crate btctax_cli 

Source
Expand description

btctax-cli: the CLI + reconciliation library that wires the encrypted vault (btctax-store), ingest (btctax-adapters), and the pure projection (btctax-core) into the Phase-1 command surface (spec §11). The library is I/O-explicit and deterministic; the binary (main.rs) is a thin clap dispatch. PRIVACY: tests use only temp vaults + synthetic fixtures; no real user file is ever read.

Re-exports§

pub use cli::Cli;
pub use cmd::tranche::guard_allocation_vs_tranche;
pub use cmd::promote::PROMOTE_ACK_PHRASE;
pub use cmd::admin::promote_export_gate;
pub use config::CliConfig;
pub use session::BulkFilter;
pub use session::BulkIncomeFilter;
pub use session::BulkIncomePlan;
pub use session::BulkIncomeRow;
pub use session::BulkLinkPlan;
pub use session::BulkLinkRow;
pub use session::BulkReclassifyOutflowPlan;
pub use session::BulkReclassifyOutflowRow;
pub use session::BulkResolvePlan;
pub use session::BulkResolveRow;
pub use session::BulkStiFilter;
pub use session::BulkStiPlan;
pub use session::BulkStiRow;
pub use session::BulkVoidPlan;
pub use session::BulkVoidRow;
pub use session::Frame;
pub use session::MatchAction;
pub use session::MatchProposal;
pub use session::Session;

Modules§

bulk_estimated
bulk_estimated_proceeds side-table — flags each disposal whose proceeds were derived from an auto-FMV (daily-close market value) by the bulk-reclassify-outflow path, rather than a real user-entered sale price. Keyed by the EventId::canonical() string of the transfer_out_event, which IS the eventual Disposal.event (fold pushes Disposal{event: eff.id.clone()} using the ORIGINAL TransferOut id — so the Disposals-tab join lands). Modeled on donation_details.rs / optimize_attest.rs discipline (idempotent DDL, defensive init_table guard on every accessor).
cli
The clap-4 command surface for btctax, extracted into the library so tooling (the xtask man-page generator) can obtain the Command via Cli::command() (clap::CommandFactory). The binary (main.rs) is a thin dispatch over these types.
cmd
config
The CLI’s persisted projection-config knob (TP8 self-transfer fee treatment + lot method), stored in a cli_config(key,value) table inside the vault DB. It is a projection input parameter, not ledger state (NFR6): the event log remains the sole source of truth; this only selects a swappable rule. TP8 default is (c), USER-MANDATED — never default to (b).
donation_details
donation_details side-table — persists Form 8283 Section-B appraiser + structured-donee metadata for each donation event. Keyed by the donation’s EventId::canonical() string. Modeled on optimize_attest.rs discipline (idempotent DDL, defensive init_table guard on every accessor, JSON storage via serde_json — same as tax_profile.rs). The data is POST-HOC form-completion metadata; it does NOT enter the fold or projection.
eventref
Parse CLI references back into core types. The primary case is the canonical EventId string the engine prints (EventId::canonical()): import|<src>|<source_ref…>, conflict|<src>|<source_ref…>|<fp>, decision|<seq>. source_ref itself may contain | (adapters mint direction-scoped refs like out|cb-send), so import rejoins parts[2..] and conflict takes the LAST part as the fingerprint.
input_form_store
Per-year return_inputs_draft(year, inputs_json, schema_version, parked) side-table — the input form’s crash-recovery scratch, INVISIBLE to resolve.rs. parked = 1 marks a parked committed return (C-1).
optimize_attest
optimize_attestation side-table — persists the user’s per-disposal contemporaneous-ID attestations (a projection input, not ledger state). The attested_set accessor feeds the compliance_overlay as its attested: &BTreeSet<EventId> argument; get returns the stored attestation text so the overlay can enforce attested-binds-the-exact-selection (R2-I1: a later divergent pick is NOT covered). Modeled on tax_profile.rs discipline (idempotent DDL, defensive guard on every accessor, BTreeSet for NFR4 determinism).
price_cache
Resolve the local price-cache path (#41 Part C). dirs lives HERE (and in btctax-update-prices), NOT in btctax-adapters [R0-M2/r2 M-A] — the adapter’s LayeredPrices takes an ALREADY-resolved cache_path and stays a pure format/provider crate (no dirs, no network). The cache is a documented LOCAL INPUT the offline projection layers OVER the bundled dataset; it is populated ONLY by the separate btctax-update-prices binary, so btctax-cli itself carries NO network dependency.
render
Text rendering of CLI outputs (FR9 verify, FR4 report/show) + FR10 CSV export. Pure string-building over engine data — the CLI displays; the engine computes (NFR4/NFR5).
resolve
Single profile-source resolver (full-return v1, SPEC §4.12 / G4).
return_inputs
Per-year return_inputs(year, inputs_json) side-table — the full-return v1 input surface (line items + PII + payments). A projection input, not ledger state (NFR6). Mirrors tax_profile.rs exactly (idempotent DDL, robust-to-older-vaults guard, typed error on bad JSON) — one JSON-encoded ReturnInputs per tax year, stored inside the encrypted vault.
session
Session wraps one open btctax_store::Vault and is the single seam every command opens. The passphrase is ALWAYS a parameter — production resolves it in main (prompt/env); tests inject a constructed Passphrase. project() runs the pure core projection over the bundled price dataset.
tax_profile
Per-year tax_profile(year, profile_json) side-table — a projection input, not ledger state (NFR6). Stores one JSON-encoded TaxProfile per tax year. Modeled on config.rs’s cli_config side-table discipline (idempotent DDL, robust-to-older-vaults guard, typed error on bad JSON). Called by Session::from_fresh_vault and as a defensive guard at the top of every read/write (same pattern as config::init_config_table / config::read_config).
testonly
Shared synthetic corpora + per-journey fixtures for the worked-example journeys (J1–J9).

Enums§

CliError

Constants§

ATTEST_PHRASE
The exact phrase a user must affirm to export a form/data file while the ledger is pseudo-reconciled (sub-project 3). Compared TRIMMED, case-SENSITIVE, exact. The prompt + both error strings are BUILT from this constant [R0-M1] so there is no drift (a KAT asserts they contain it). pub so btctax-tui shares it [R0-r2-N2].
EXPORT_OUT_HINT
UX-P4-8 hint: shown when an export --out directory cannot be created (a colliding file, a missing parent, or a permission problem).
VAULT_OPEN_HINT
UX-P4-8 hint: shown when a --vault cannot be opened (missing/unreadable path).

Functions§

cli_io_with_path
Re-wrap a pathless I/O failure with the offending PATH + a one-clause hint (UX-P4-8). Enriches BOTH shapes an export write can produce: a raw CliError::Io (a write/flush mid-write) AND a CliError::Store(StoreError::Io) (a mkdir_owner_only/open_owner_only under out_dir — e.g. a SUBPATH collision like out_dir/lots.csv already existing as a directory, which ?-converts through From<StoreError>). A CliError::Csv (a serialization error, not a path problem) and every other variant pass through unchanged.
require_attestation
PURE exact-compare attestation gate — NO I/O, NO TTY read [R0-I2]. The interactive prompt lives in the caller (the export-snapshot main.rs arm / the btctax-tui export modal); this helper only compares, keeping the library I/O-explicit and the KATs deterministic (no env-dependent branch).
store_io_with_path
Re-wrap a StoreError I/O failure with the offending PATH + a one-clause hint (UX-P4-8). ONLY the pathless StoreError::Io is enriched; every other variant (WrongPassphrase, Locked, HalfCreatedVault, …) passes through unchanged — each already carries its own precise meaning and must NOT be masked behind a generic path/hint.