# Jarca Ledger MCP Data Model - Baseline Mode: observed - Baseline Seed: `.stage-pilot/bootstrap/baseline.yaml` - Status: draft - Owner: Jarca / project maintainer - Last Updated (KST): 2026-06-27 10:17 - Source Discovery / Batch: bootstrap-baseline ## Project Summary - Jarca 가계부 전용 MCP 서버와 Streamlit 대시보드로 계좌/카드 거래, 예산, 분류 규칙, import, 현금흐름 분석을 SQLite에 저장하고 운영한다. ## Purpose - This document captures the current data-model baseline for future Discovery, REQ, Batch, and Release work. - It focuses on durable entities, state rules, consistency rules, and persistence boundaries rather than implementation-only details. ## Persistence Backend - SQLite database at `~/.local/share/jarca/ledger.sqlite3` by default. - Override path through `JARCA_LEDGER_DB_PATH`. - Schema initialization and migrations are managed by `jarca_ledger_mcp/db.py`. ## Entity: LedgerAccount - Source of Truth: `ledger_accounts` - Purpose: Represents bank, card, cash, investment, or loan accounts used to attach transaction evidence and balances. - Lifecycle: created -> updated -> inactive/archived - Key Fields: - `id` :: text :: stable account identifier - `name` :: text :: operator-facing account name - `type` :: text :: bank/card/cash/investment/loan classification - `institution` :: text :: financial institution or source - `account_number_masked` :: text :: masked account identifier - `holder_name` :: text :: owner context for transfer matching - `last_balance` :: integer :: latest known balance when available - Relationships: - `transactions.account_id` links rows to accounts. - State Rules: - `active=false` hides accounts from default lists without deleting history. ## Entity: Transaction - Source of Truth: `transactions` - Purpose: Represents imported or manually entered financial event evidence. - Lifecycle: created/imported -> categorized/reconciled -> soft-deleted or retained - Key Fields: - `transaction_date` :: date text :: ledger date - `posted_date` / `transaction_datetime` :: text :: source timing detail where available - `type` :: text :: `income`, `expense`, `transfer`, `refund`, or `adjustment` - `amount` :: integer :: positive KRW amount - `category` / `subcategory` :: text :: household classification - `merchant`, `counterparty`, `description`, `payment_method` :: text :: evidence and display fields - `source`, `external_id`, `import_batch_id`, `raw_summary`, `raw_payload` :: text :: provenance and audit fields - `memo` :: text :: operator notes and reconciliation tags - `status` :: text :: active/deleted/review lifecycle state where used - Relationships: - belongs to LedgerAccount through `account_id` - linked to ImportBatch through `import_batch_id` - interpreted with LedgerCategory through `category`/`subcategory` - State Rules: - Amount is stored positive; `type` determines direction. - Cancellation/refund rows should use `refund` type when confirmed. - Manual link evidence should be memo-tagged rather than silently rewritten. ## Entity: LedgerCategory - Source of Truth: `ledger_categories` - Purpose: Defines category/subcategory labels and their cashflow semantics. - Lifecycle: seeded/created -> updated -> inactive/deleted - Key Fields: - `category` :: text - `subcategory` :: text - `cashflow_kind` :: text :: `income`, `expense`, `transfer`, `investment`, `debt_payment`, `exclude`, `unknown` - `sort_order`, `memo`, `active` - Relationships: - Referenced by Transaction classification. - Targeted by CategoryRule results. - State Rules: - `cashflow_kind` controls inclusion in actual household cashflow reports. - Transfer, investment, exclude, and unresolved kinds are not actual household spending unless a report explicitly asks for account movements. ## Entity: CategoryRule - Source of Truth: `category_rules` - Purpose: Automatic classification policy for transactions. - Lifecycle: created -> previewed/applied -> updated/deactivated/deleted - Key Fields: - `match_field` :: text :: field to inspect - `pattern` :: text :: match pattern - `match_type` :: text :: contains/equals/regex - `category` / `subcategory` :: text :: classification target - `priority` :: integer :: deterministic ordering - `amount_min`, `amount_max`, `day_of_month` :: integer nullable :: optional constraints - `person`, `is_fixed`, `confidence`, `memo`, `active` - Relationships: - Applies to Transaction rows. - Should target valid or intentional category/subcategory labels. - State Rules: - Preview should precede broad application when changing classification behavior. - More specific/high-priority rules should avoid accidentally overriding unrelated evidence. ## Entity: ImportBatch - Source of Truth: `import_batches` - Purpose: Tracks grouped imports for audit and rollback. - Lifecycle: previewed -> imported -> optionally rolled back - Key Fields: - `id` :: text :: import batch identifier - `source` :: text :: source kind - `file_path` / source metadata where stored - `inserted_count`, `skipped_duplicate_count`, `created_at`, `rolled_back_at` - Relationships: - Transaction rows reference `import_batch_id`. - State Rules: - Rollback should soft-delete by default. - Duplicate imports with `skip_duplicates=True` may insert zero rows; that is not automatically an error. ## Entity: Budget - Source of Truth: budget table/service functions - Purpose: Monthly category/subcategory/person budget target. - Lifecycle: created/updated -> compared against actual spending - Key Fields: - `month`, `category`, `subcategory`, `person`, `amount`, `currency`, `memo` - Relationships: - Compared against Transaction aggregates by report functions. ## Entity: LedgerBackupArtifact - Source of Truth: filesystem under `/root/.local/share/jarca/backups/ledger/` by default - Purpose: Timestamped SQLite backup artifact used for operational recovery and validation smoke checks. - Lifecycle: created -> listed/status-checked -> retained/pruned by policy -> optionally restored by script/runbook after approval - Key Evidence Fields: - `path` :: text :: backup file path outside repository - `size_bytes` :: integer :: file size metadata - `mtime` :: text :: filesystem modification time - `sha256` :: text :: file checksum - `integrity_check` :: text :: SQLite integrity result - `table_counts` / `aggregate_totals` :: metadata-only validation evidence - State Rules: - Keep backups from the most recent 30 days or newest 20 files. - Backup artifacts and validation DB copies must not be committed to git. - Restore execution is not a persisted MCP operation and requires script/runbook approval controls. ## Consistency Rules - Actual cashflow reports include only categories whose `cashflow_kind` represents actual income or expense according to report semantics. - Account movement summaries should be separate from actual household income/expense summaries. - Cross-account auto-matching requires same date, same amount, opposite direction, and compatible source/owner evidence. - External counterparty securities transfers are review items unless matched or explicitly confirmed. - Import evidence fields are retained for audit and future correction. - DB corrections should be narrow and memo-tagged. ## Persistence Notes - Schema changes should be additive/idempotent unless a destructive migration is explicitly approved and backed up. - Operational backup/status evidence may include only path, size, mtime, checksum, integrity, row counts, and aggregate totals. - Validation DB copies should live outside the repository and should be selected explicitly via `JARCA_LEDGER_DB_PATH` when used. - Passwords for encrypted imports are runtime-only inputs and are not part of the persisted model. - Raw payloads may contain sensitive financial evidence and should not be committed to git. ## Current Gaps / Planned Changes - Formal schema migration documentation should be added before larger DB changes. - Some UI workflows need final E2E verification against real rows. - Statement-unavailable account handling needs a documented manual evidence model. ## Change Log - 2026-06-26 22:24 KST: Created by `bootstrap-baseline` from repository observation. - 2026-06-27 10:17 KST: BAT-002/REQ-002 기준으로 LedgerBackupArtifact와 metadata-only evidence 정책 추가.