15 KiB
15 KiB
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-07-01
- Source Discovery / Batch: bootstrap-baseline, BAT-008, BAT-009
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.sqlite3by 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 identifiername:: text :: operator-facing account nametype:: text :: bank/card/cash/investment/loan classificationinstitution:: text :: financial institution or sourceaccount_number_masked:: text :: masked account identifierholder_name:: text :: owner context for transfer matchinglast_balance:: integer :: latest known balance when availablelast_synced_at:: text :: 기준 잔액 스냅샷 시각. 정기 대조는 월말 23:59 KST, 수시 대조는 사용자 입력 시각statement_status:: text ::unknown,import_supported,manual_only,partial_importliquidity_bucket:: text ::cash,investment,deposit,real_estate,loan,other; 자산 유동성/구성/순자산 집계의 계좌 단위 권위 소스
- Relationships:
transactions.account_idlinks rows to accounts.
- State Rules:
active=falsehides accounts from default lists without deleting history.manual_onlyis the statement-unavailable class;partial_importremains eligible for manual supplementation and balance reconciliation.- Balance reconciliation is report/preview first: compare
baseline_balance/baseline_atagainst the latestbalance_afteror net account transaction delta, with 1,000 KRW absolute tolerance. - 계좌 기반 자산/부채는
last_balance를 현재 평가 권위 소스로 사용하고,last_synced_at을 기준일,memo를 출처 메모로 보존한다. - 거래로 산출되지 않는 비거래 자산/부채는
ManualAsset에 별도 저장한다. 계좌와 수기 자산을 같은 항목으로 중복 등록하지 않는다. liquidity_bucket='loan'은 자산 구성 비율 분모에서 제외하고 총부채/순자산 산식에만 반영한다.last_balance가 없는 계좌/자산은 임의 거래 합계로 추정하지 않는다.
Entity: ManualAsset
- Source of Truth:
manual_assets - Purpose: Stores non-transaction-derived assets/liabilities such as real estate, deposits, loans, and other manually valued holdings that should not be mixed into account rows.
- Lifecycle: created -> revalued/updated -> inactive/archived
- Key Fields:
id:: text :: stable manual asset identifiername:: text :: operator-facing asset/liability nameliquidity_bucket:: text ::cash,investment,deposit,real_estate,loan,othervaluation_amount:: integer nullable :: latest manually entered valuation/balance; null means excluded from valuation totalsvaluation_date:: date text :: valuation basis datecurrency:: text :: defaultKRWsource_note:: text :: valuation evidence/source memomemo:: text :: operator noteactive:: integer/bool :: inactive rows are excluded from default read reports
- Relationships:
- Referenced by
asset_snapshots.source_type='manual_asset'andsource_idwhen a month-end valuation is snapshotted.
- Referenced by
- State Rules:
manual_assetsis the live authority source for non-transaction assets/liabilities.- Create/update mutation validates name, date, liquidity bucket, source evidence fields, and stores changes additively in the existing row; inactive rows are hidden from default valuation reports.
- Soft delete/deactivate (
active=false) is the default deletion semantic so historicalasset_snapshots.source_idremains reproducible. Hard delete is exceptional cleanup only. - Missing
valuation_amountrows are excluded; transaction sums are not used as a substitute. loanbucket values are treated as liabilities and subtracted from asset-bucket totals.
Entity: AssetSnapshot
- Source of Truth:
asset_snapshots - Purpose: Append-only item-level record of a basis-date asset/liability valuation produced from the live authority sources.
- Lifecycle: appended at month-end/manual close -> read for point-in-time reports and timeseries
- Key Fields:
id:: text :: snapshot row identifierbasis_date:: date text :: valuation date represented by the rowsource_type:: text ::accountormanual_assetsource_id:: text :: source entity identifier when availablename:: text :: snapshot display name copied from the source at capture timeamount:: integer nullable :: snapshotted valuation amountliquidity_bucket:: text :: bucket copied from the source at capture timevaluation_source,source_note,memo:: text :: evidence and operator contextsnapshot_run_id:: text :: month-end close run identifier for rows created togethercorrection_of_run_id:: text :: previous close run corrected by this append-only run when applicablecorrection_reason:: text :: operator reason required for same-date re-close/correctionis_correction:: integer/bool :: marks correction close rowsclosed_at:: text :: close execution timestamp copied across the runcreated_at:: text :: snapshot row creation timestamp
- Relationships:
- Represents a historical record of
LedgerAccount.last_balanceorManualAsset.valuation_amountrather than a new primary input source.
- Represents a historical record of
- State Rules:
- Snapshot rows are append-only. Existing rows are not destructively overwritten.
preview_asset_snapshot_closecomputes the source item list, bucket totals, total assets/liabilities, net worth, and warnings without writing rows.close_asset_snapshotwrites one run of item-level rows for a basis date from live authority sources. Same-date re-close requirescorrection_reason, appends a new correction run, and links to the previoussnapshot_run_idwhen available.- Read reports choose the latest run for a basis date when run metadata exists, preserving original and correction rows for audit while avoiding double counting.
- Basis-date snapshot reports prefer stored
asset_snapshotsrows when rows exist for the date; otherwise read reports can fall back to live authority sources.
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 dateposted_date/transaction_datetime:: text :: source timing detail where availabletype:: text ::income,expense,transfer,refund, oradjustmentamount:: integer :: positive KRW amountcategory/subcategory:: text :: household classificationmerchant,counterparty,description,payment_method:: text :: evidence and display fieldssource,external_id,import_batch_id,raw_summary,raw_payload:: text :: provenance and audit fieldsmemo:: text :: operator notes and reconciliation tagsstatus:: 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
- belongs to LedgerAccount through
- State Rules:
- Amount is stored positive;
typedetermines direction. - Cancellation/refund rows should use
refundtype when confirmed. - Manual link evidence should be memo-tagged rather than silently rewritten.
- Amount is stored positive;
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:: textsubcategory:: textcashflow_kind:: text ::income,expense,transfer,investment,debt_payment,exclude,unknownsort_order,memo,active
- Relationships:
- Referenced by Transaction classification.
- Targeted by CategoryRule results.
- State Rules:
cashflow_kindcontrols 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 inspectpattern:: text :: match patternmatch_type:: text :: contains/equals/regexcategory/subcategory:: text :: classification targetpriority:: integer :: deterministic orderingamount_min,amount_max,day_of_month:: integer nullable :: optional constraintsperson,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 identifiersource:: text :: source kindfile_path/ source metadata where storedinserted_count,skipped_duplicate_count,created_at,rolled_back_at
- Relationships:
- Transaction rows reference
import_batch_id.
- Transaction rows reference
- State Rules:
- Rollback should soft-delete by default.
- Duplicate imports with
skip_duplicates=Truemay 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 repositorysize_bytes:: integer :: file size metadatamtime:: text :: filesystem modification timesha256:: text :: file checksumintegrity_check:: text :: SQLite integrity resulttable_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_kindrepresents 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.
- Dashboard/MCP asset and net-worth reports use a shared valuation helper: account-backed items from
accounts.last_balanceplus non-transaction items frommanual_assets. - Net worth is asset buckets (
cash,investment,deposit,real_estate,other) minus absoluteloanliabilities; missing valuations are excluded and reported, never inferred from transactions.
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_PATHwhen 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 is tracked by REQ-003/BAT-003; future work may add a dedicated reconciliation workbench and persistent review-decision queue.
- BAT-009 implements manual asset CRUD mutation and month-end snapshot preview/close/correction service/MCP/dashboard workflow. Future work may add automatic market/real-estate valuation or scheduled month-end close.
Change Log
- 2026-06-26 22:24 KST: Created by
bootstrap-baselinefrom repository observation. - 2026-06-27 10:17 KST: BAT-002/REQ-002 기준으로 LedgerBackupArtifact와 metadata-only evidence 정책 추가.
- 2026-06-29 KST: REQ-003/BAT-003 기준으로
accounts.statement_status와 수동 잔액대조 preview 모델 추가. - 2026-06-29 KST: REQ-005/BAT-005 기준으로
accounts.liquidity_bucket,last_balance기반 자산 유동성/부채/순자산 규칙 추가. - 2026-06-30 KST: REQ-009/REQ-010/BAT-008 기준으로
manual_assets,asset_snapshots, 권위 소스(accounts.last_balance+manual_assets), 순자산 산식/미평가 제외 정책 추가. - 2026-07-01 KST: REQ-011/REQ-012/BAT-009 기준으로 manual asset CRUD, snapshot preview/close, append-only correction metadata, latest-run read policy 추가.