Files
jarca-ledger-mcp/docs/data-model.md
T
genichin d9182f28f2 feat: enforce import provenance exposure policy (#2)
Merge BAT-017 / REQ-021 implementation after delivery-runner implementation, independent QC, and passing GitHub Actions CI.
2026-07-09 18:44:19 +09:00

18 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-09
  • Source Discovery / Batch: bootstrap-baseline, BAT-008, BAT-009, REQ-021/BAT-017

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
    • last_synced_at :: text :: 기준 잔액 스냅샷 시각. 정기 대조는 월말 23:59 KST, 수시 대조는 사용자 입력 시각
    • statement_status :: text :: unknown, import_supported, manual_only, partial_import
    • liquidity_bucket :: text :: cash, investment, deposit, real_estate, loan, other; 자산 유동성/구성/순자산 집계의 계좌 단위 권위 소스
  • Relationships:
    • transactions.account_id links rows to accounts.
  • State Rules:
    • active=false hides accounts from default lists without deleting history.
    • manual_only is the statement-unavailable class; partial_import remains eligible for manual supplementation and balance reconciliation.
    • Balance reconciliation is report/preview first: compare baseline_balance/baseline_at against the latest balance_after or 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 identifier
    • name :: text :: operator-facing asset/liability name
    • liquidity_bucket :: text :: cash, investment, deposit, real_estate, loan, other
    • valuation_amount :: integer nullable :: latest manually entered valuation/balance; null means excluded from valuation totals
    • valuation_date :: date text :: valuation basis date
    • currency :: text :: default KRW
    • source_note :: text :: valuation evidence/source memo
    • memo :: text :: operator note
    • active :: integer/bool :: inactive rows are excluded from default read reports
  • Relationships:
    • Referenced by asset_snapshots.source_type='manual_asset' and source_id when a month-end valuation is snapshotted.
  • State Rules:
    • manual_assets is 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 historical asset_snapshots.source_id remains reproducible. Hard delete is exceptional cleanup only.
    • Missing valuation_amount rows are excluded; transaction sums are not used as a substitute.
    • loan bucket 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 identifier
    • basis_date :: date text :: valuation date represented by the row
    • source_type :: text :: account or manual_asset
    • source_id :: text :: source entity identifier when available
    • name :: text :: snapshot display name copied from the source at capture time
    • amount :: integer nullable :: snapshotted valuation amount
    • liquidity_bucket :: text :: bucket copied from the source at capture time
    • valuation_source, source_note, memo :: text :: evidence and operator context
    • snapshot_run_id :: text :: month-end close run identifier for rows created together
    • correction_of_run_id :: text :: previous close run corrected by this append-only run when applicable
    • correction_reason :: text :: operator reason required for same-date re-close/correction
    • is_correction :: integer/bool :: marks correction close rows
    • closed_at :: text :: close execution timestamp copied across the run
    • created_at :: text :: snapshot row creation timestamp
  • Relationships:
    • Represents a historical record of LedgerAccount.last_balance or ManualAsset.valuation_amount rather than a new primary input source.
  • State Rules:
    • Snapshot rows are append-only. Existing rows are not destructively overwritten.
    • preview_asset_snapshot_close computes the source item list, bucket totals, total assets/liabilities, net worth, and warnings without writing rows.
    • close_asset_snapshot writes one run of item-level rows for a basis date from live authority sources. Same-date re-close requires correction_reason, appends a new correction run, and links to the previous snapshot_run_id when 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_snapshots rows 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 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
    • raw_payload write policy is minimize: only source-specific allowlisted normalized keys may be persisted; raw document dumps, full file paths, passwords, tokens/secrets, and arbitrary parser columns are excluded.
    • 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
    • filename :: text :: masked basename plus source-hash prefix for operator correlation; full local source paths must not be stored on new writes
    • memo :: text/json :: compact batch metadata such as source hash, validation summary, or source-specific sheet/page references used for read-time provenance shaping
    • 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.
    • Read surfaces should expose sanitized provenance envelopes: default minimal, explicit operator-facing operator-summary, and explicit debug-gated diagnostics without full document/path leakage.

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.

Entity: ReviewDecision

  • Source of Truth: review_decisions
  • Purpose: 공통 review/workbench envelope for cross-transfer review rows, reconciliation targets, and uncategorized recommendation items.
  • Lifecycle: pending -> decided/held/needs_recheck/ignored -> pending release when operator clears hold/recheck.
  • Key Fields: id, target_type, target_id, status, decision_type, reason_code, memo, operator, decided_at, review_after, sanitized JSON target_payload, created_at, updated_at.
  • State Rules: decisions are non-destructive and do not rewrite accounting fields by themselves. Existing read contracts are preserved by attaching additive review_status / review_decision metadata. target_payload omits raw payloads, passwords, tokens, secrets, and source file paths.

Entity: ReconciliationSession

  • Source of Truth: reconciliation_sessions
  • Purpose: 계좌별/기준일별 잔액대조 session close/open state and difference evidence.
  • Lifecycle: open -> closed, with needs_recheck/ignored available for operator triage.
  • Key Fields: id, account_id, basis_date, expected_balance, actual_balance, difference, status, closed_at, source_note, memo, operator, created_at, updated_at.
  • State Rules: account/basis-date rows are upserted idempotently; close records closed_at; destructive delete/reset workflow is not exposed.

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.
  • Dashboard/MCP asset and net-worth reports use a shared valuation helper: account-backed items from accounts.last_balance plus non-transaction items from manual_assets.
  • Net worth is asset buckets (cash, investment, deposit, real_estate, other) minus absolute loan liabilities; missing valuations are excluded and reported, never inferred from transactions.
  • Review workbench state is sourced from review_decisions; pending/held/recheck counts must not be inferred by overwriting raw transaction evidence.
  • Reconciliation operating state is sourced from reconciliation_sessions; last close time is the max closed session closed_at.

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; BAT-017 constrains new writes to minimized allowlisted payloads only and leaves legacy row cleanup to a separate approved follow-up.
  • ReviewDecision target_payload is sanitized to omit raw_payload, passwords, tokens, secrets, and file paths before persistence.

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; REQ-020/BAT-016 adds dedicated reconciliation sessions and persistent review-decision queue metadata.
  • 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-07-09 KST: REQ-021/BAT-017 기준으로 import provenance exposure policy, transactions.raw_payload=minimize, import_batches.filename masked-basename persistence, and explicit debug gate expectations를 반영.
  • 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 정책 추가.
  • 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 추가.
  • 2026-07-08 KST: REQ-020/BAT-016 기준으로 review_decisions, reconciliation_sessions, review 상태값, payload 최소보관/마스킹 규칙, 운영 허브 집계 source-of-truth를 추가.