Attachments, statements, reconciliations, TIN vault, counterparty policy
check / check (push) Waiting to run

MCP: books.link_attachment, unlink_attachment, attachments; link_to on
attach_receipt and file_document; record_statement, statements;
books.reconcile previews and, confirmed against a recorded statement,
records the reconciliation; void_reconciliation, reconciliations;
import_bank_csv links its source file; digest lists unreconciled
accounts.

TIN vault: books.set_w9 takes the TIN and the form into the encrypted
vault (last four in the books); books.vendor_1099 include_tins and
save_csv_to for the CPA's copy; books.get_w9; books.purge_tin. A leak
test scans every tool output, the journal, the database, and the blobs.

[books] parties = off | suggest | require (default suggest): every
preview names the entry's party or suggests likely ones; require refuses
to post until it names one or is marked as having none (entry.no_party).

Viewer: documents on every subject page; statements and reconciliation
history per account; reconciliation pages; reconcile and
no-counterparty attention items; party money by period (paid out,
received in, net, what for, by month); Needs attention gets its own
full-width section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-15 15:42:37 -06:00
1 parent e265ed4339
commit ae927c3f73
41 files changed
+8463 -465

No files matched your search

+27 -2
View File
@@ -18,9 +18,12 @@ use crate::blob::BlobStore;
use crate::error::StoreError;
use crate::journal::{GENESIS_PREV, JournalLine, sha256_hex};
use crate::store::{
Attachment, BLOBS_DIR, DB_FILE, JOURNAL_FILE, Store, apply_line_to_sqlite, compare_projections,
projection_rows, query_attachments, read_attachment_bytes, replay_line_into_ledger,
Attachment, BLOBS_DIR, DB_FILE, JOURNAL_FILE, Reconciliation, Statement, Store, Subject,
apply_line_to_sqlite, compare_projections, projection_rows, query_attachment_links,
query_attachments, query_reconciliations, query_statements, read_attachment_bytes,
replay_line_into_ledger,
};
use ledger_core::AccountId;
use ledger_core::{Currency, EntryId, Ledger};
use rusqlite::Connection;
use std::io::{Read, Seek, SeekFrom};
@@ -216,6 +219,28 @@ impl Snapshot {
query_attachments(&self.conn, entry_id)
}
/// Every attachment link beyond a receipt's filing entry, as
/// (attachment id, subject), by attachment then subject: what
/// [`Store::attachment_links`] reads, for every attachment at once.
pub fn attachment_links(&self) -> Result<Vec<(u64, Subject)>, StoreError> {
query_attachment_links(&self.conn)
}
/// Recorded bank and card statements, optionally one account's, by
/// period end (as [`Store::statements`]).
pub fn statements(&self, account: Option<AccountId>) -> Result<Vec<Statement>, StoreError> {
query_statements(&self.conn, account)
}
/// Reconciliations, voided ones included, optionally one account's,
/// by date (as [`Store::reconciliations`]).
pub fn reconciliations(
&self,
account: Option<AccountId>,
) -> Result<Vec<Reconciliation>, StoreError> {
query_reconciliations(&self.conn, account)
}
/// Compare the writer's SQLite database (opened read-only) with this
/// snapshot's own projection of the journal, every table, row for row.
///