Files
jarca-ledger-mcp/docs/runtime-flows.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

16 KiB

Jarca Ledger MCP Runtime Flows

  • 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-006, BAT-007, BAT-008, BAT-010, BAT-012, BAT-013, BAT-014, dcy-013/BAT-015, dcy-012/REQ-020/BAT-016, REQ-021/BAT-017
  • Primary Runtime: mixed

Project Summary

  • Jarca 가계부 전용 MCP 서버와 Streamlit 대시보드로 계좌/카드 거래, 예산, 분류 규칙, import, 현금흐름 분석, 자산/스냅샷 운영을 SQLite에 저장하고 제공한다.

Purpose

  • This document is the current execution-flow baseline for the project.
  • It is a cross-cutting reference document for Discovery, REQ, Batch Design, Batch Verification, and implementation updates.

Scope

  • Covers representative command, MCP, dashboard, import, reconciliation, snapshot, and verification flows.
  • Does not duplicate full acceptance criteria or low-level implementation details.

Covered Entry Points

  • jarca-ledger-mcp :: MCP stdio server for local Hermes tool calls, or streamable-http server when configured by env.
  • jarca-ledger Docker service :: Streamable HTTP MCP endpoint at http://<synology-host>:8000/mcp.
  • dashboard/app.py :: Streamlit local dashboard.
  • pytest :: regression test runner.
  • .github/workflows/ci.yml :: GitHub Actions CI gate runner for PR/push/manual checks.

Shared Components

  • SQLite database at ~/.local/share/jarca/ledger.sqlite3 by default for local runs; Docker service uses JARCA_LEDGER_DB_PATH=/data/ledger.sqlite3 backed by /volume1/docker/jarca-ledger/data.
  • jarca_ledger_mcp/service.py compatibility facade over application modules.
  • jarca_ledger_mcp/infrastructure/sqlite/* for DB path resolution, schema, migration, and connection lifecycle.
  • jarca_ledger_mcp/adapters/mcp/tool_contracts.py + adapters/mcp/server.py for MCP contract and registration seams.
  • jarca_ledger_mcp/adapters/streamlit/*_gateway.py + service_gateway.py compatibility aggregator for dashboard-facing service calls.
  • jarca_ledger_mcp/infrastructure/parsers/* plus legacy parser modules for KB/Toss/SeoulPay sources.

Flow: Docker network MCP service

  1. Docker daemon starts the jarca-ledger container from jarca-ledger:latest with restart: unless-stopped.
  2. Compose mounts /volume1/docker/jarca-ledger/data to /data and sets JARCA_LEDGER_DB_PATH=/data/ledger.sqlite3.
  3. jarca-ledger-mcp starts FastMCP with JARCA_MCP_TRANSPORT=streamable-http, JARCA_MCP_HOST=0.0.0.0, JARCA_MCP_PORT=8000, and path /mcp.
  4. Finance agents connect to http://<synology-host>:8000/mcp or a shared Docker network DNS endpoint.
  5. The MCP adapter routes tool calls through adapters/mcp/tool_contracts.py and existing application/persistence services.
  6. Docker healthcheck verifies TCP readiness on 127.0.0.1:8000; functional readiness is verified by MCP tool discovery and ledger_health_check.

Flow: Operating DB migration to jarca-ledger container

  1. Identify source DB in the legacy jarca container: /root/.local/share/jarca/ledger.sqlite3.
  2. Create a consistent source snapshot using SQLite Connection.backup() rather than copying a live DB file directly.
  3. Back up the current target /data/ledger.sqlite3 under /data/backups/ before replacement.
  4. Stop jarca-ledger, remove target WAL/SHM sidecar files, copy the snapshot to /data/ledger.sqlite3, and restart.
  5. Verify Docker health, SQLite PRAGMA integrity_check, table counts, sha256, and MCP get_ledger_db_status.

Flow: MCP server tool call

  1. Hermes MCP client invokes a tool exposed by jarca_ledger_mcp.server / jarca_ledger_mcp.adapters.mcp.server.
  2. MCP adapter forwards arguments to the matching callable exposed by adapters/mcp/tool_contracts.py.
  3. Service facade routes into the relevant application module.
  4. Application code opens SQLite through infrastructure/sqlite helpers, validates inputs, and performs the operation.
  5. Application returns a dictionary payload with success data or error information; import-related provenance is expected to be sanitized for the requested exposure level.
  6. Hermes surfaces the tool result to the user or uses it in a follow-up workflow.

MCP provenance exposure boundary

  • Default finance-agent/tool responses use minimal provenance exposure.
  • Operator-facing surfaces may request operator-summary when masked filename, source-hash prefix, or validation summary are needed for audit triage.
  • Debug details require an explicit debug-gated path and still exclude passwords, tokens/secrets, and full source document dumps by default.

Flow: Streamlit dashboard operation

  1. Operator starts streamlit run dashboard/app.py --server.address 0.0.0.0 --server.port 8501.
  2. Dashboard reads the configured/default SQLite database.
  3. User navigates to 요약, 자산/마감, 거래내역, 확인필요 큐, 미분류, 분류 규칙, 카테고리, 계좌, or Import pages.
  4. UI calls page/domain gateways under jarca_ledger_mcp.adapters.streamlit rather than giant implementation modules directly.
  5. Gateways delegate to the service facade/application modules and return data to the page.
  6. UI displays success/error status and refreshes visible tables.

Flow: Dashboard operations hub overview

  1. Operator opens the 요약 page.
  2. Dashboard calls get_monthly_cashflow_report(month) using transactions.transaction_date and ledger_categories.cashflow_kind semantics.
  3. Dashboard calls get_asset_liquidity_report, which uses the shared valuation helper: account-backed assets from accounts.last_balance plus active manual_assets rows when present.
  4. If manual_assets and asset_snapshots are empty, the report keeps the REQ-005 account-only fallback and preserves existing totals/keys.
  5. Dashboard renders sections in REQ-005 priority order: this-month actual income/expense/net/savings rate, asset liquidity, asset composition, budget/spend, operational warnings.
  6. Missing last_balance or manual_assets.valuation_amount values are excluded from asset totals and surfaced as warnings.

Flow: Asset snapshot and net-worth workflow

  1. Operator can open 자산/마감 in Streamlit or call snapshot tools through MCP.
  2. preview_asset_snapshot_close(basis_date) computes authority-source items from accounts.last_balance + active manual_assets without DB side effects.
  3. close_asset_snapshot(basis_date, source_note, memo, correction_reason) writes append-only snapshot rows with correction metadata when re-closing the same basis date.
  4. get_asset_snapshot_report(basis_date) first checks stored snapshot rows; if none exist, it falls back to live authority sources and marks source='live_authority'.
  5. get_net_worth_timeseries(start_date, end_date, months) reads stored snapshot basis dates and applies the same asset-buckets-minus-loan formula to every point.

Flow: Import preview and import

  1. Operator chooses a supported source file: KB Bank PDF, Toss Bank PDF, Toss Securities PDF, SeoulPay XLSX, or CSV.
  2. Preview function routes through imports_service.py, which calls the parser seam under infrastructure/parsers/* and reports counts, sample rows, duplicate status, and classification preview.
  3. On explicit import, imports_service.py creates/fetches the target account, inserts non-duplicate transactions, writes minimized/raw-payload-allowlisted provenance, and records an import batch with masked filename plus source-hash prefix instead of a full local path.
  4. Reports, MCP tools, and dashboard views read the inserted rows using shared category/cashflow semantics while returning normalized provenance metadata rather than raw document evidence by default.
  5. If an import is wrong, rollback uses import batch data and soft-deletes by default.

Flow: Categorization rule lifecycle

  1. Operator creates or edits a category rule with match field, pattern, target category/subcategory, priority, and optional amount/day constraints.
  2. Preview categorization shows candidate matches without mutating rows.
  3. Apply categorization updates matching transactions and preserves audit information.
  4. Category cashflow_kind controls actual cashflow/report inclusion.

Flow: Cross-account and cancel/original reconciliation

  1. Preview helpers in cross_transfer_service.py search candidate pairs by amount, date, direction, account/source compatibility, and text similarity.
  2. Operator reviews candidates in the dashboard or runs the automatic matcher where confidence rules are satisfied.
  3. Matched self-transfers become 이체 / 본인계좌이동; investment movements become 이체 / 투자이동; ambiguous rows remain 확인필요.
  4. Cancel/refund rows can be linked to original expense rows; memo tags preserve manual link evidence.

Flow: Review decision and reconciliation workbench persistence

  1. Operator reviews cross-account transfer candidates, reconciliation differences, or uncategorized recommendations in Streamlit or via MCP.
  2. UI/MCP calls safe review decision tools such as upsert_review_decision, hold_review_decision, mark_review_recheck, and release_review_decision.
  3. review_decision_service.py validates status/decision type, minimizes target_payload, drops sensitive keys, and writes review_decisions.
  4. Reconciliation workflows call upsert_reconciliation_session or close_reconciliation_session for account/basis-date sessions stored in reconciliation_sessions.
  5. Cross-transfer queue, balance reconciliation report, and uncategorized workbench re-read persisted state and return additive fields such as review_status, review_decision, and reconciliation_session.
  6. Operating hub indicators aggregate pending review, held/recheck, unreconciled account count, last reconciliation close timestamp, and uncategorized recommendation backlog.
  7. MCP tool surface remains non-destructive; delete/reset of review/session state is intentionally absent.

Flow: Operational backup, validation DB, and restore smoke

  1. Operator captures non-sensitive DB status evidence with get_ledger_db_status: path, size, mtime, sha256, integrity check, major table row counts, and aggregate totals.
  2. Operator creates a timestamped backup in /root/.local/share/jarca/backups/ledger/ with create_ledger_backup; retention keeps the most recent 30 days or newest 20 files.
  3. Risky import, rollback, categorization apply, reconciliation, or migration work is tested first against a synthetic fixture DB or repo-external validation DB copy selected through JARCA_LEDGER_DB_PATH.
  4. Backup list/status/hash checks use list_ledger_backups and get_ledger_backup_status.
  5. Restore execution is not an MCP flow. Restore smoke uses scripts/ledger_restore_smoke.py or the runbook and requires explicit approval before overwriting an existing target DB.

Flow: CI validation gates

  1. GitHub Actions starts .github/workflows/ci.yml on pull_request, push to main, or workflow_dispatch.
  2. lint runs ruff check . with the conservative required rule set.
  3. contract-regression runs pytest tests/test_contract_regression.py with synthetic pytest temp DBs and committed contract snapshots.
  4. pytest-regression runs the non-dashboard regression suite.
  5. dashboard-app-test runs pytest tests/test_dashboard_app.py using scripts/ci_fixture_db.py synthetic DB setup.
  6. dashboard-http-smoke starts Streamlit against a synthetic DB and polls readiness.
  7. db-safety-smoke runs restore smoke through temp source/backup/target DB paths only.
  8. Any required job failure fails the workflow. Stable required-check job names remain pytest-regression, dashboard-app-test, dashboard-http-smoke, db-safety-smoke, contract-regression, and lint.

Flow: Streamlit browser evidence capture

  1. Operator runs scripts/streamlit_browser_evidence.py or starts Streamlit against a synthetic fixture DB.
  2. The script/flow refuses to use the default operating DB path for evidence capture.
  3. Browser smoke opens key pages such as 요약, 자산/마감, 분류 규칙, 확인필요 큐, and Import.
  4. Verification records rendered headings/content and browser console JS error absence.
  5. UI/dashboard-impacting batches must attach browser screenshot/DOM evidence or equivalent browser smoke notes.

Flow Constraints

  • Preview before broad import or categorization mutation where supported.
  • Do not include transfer, investment, exclude, or unresolved rows in actual household spending totals unless a report explicitly asks for account movement.
  • Preserve raw import evidence for audit and future reclassification.
  • Avoid destructive migrations without a backup/approval plan.
  • Before broad DB mutation, capture DB status evidence and create or confirm a recent backup.
  • Restore execution is script/runbook only and must not be exposed as an MCP tool.
  • Streamlit browser evidence must use synthetic/validation DBs only and must not screenshot/log real account numbers, source financial filenames, passwords, full merchant/counterparty dumps, or raw payloads.
  • CI gates must use synthetic/temp DBs only. The default operating DB path is forbidden for AppTest, HTTP smoke, and DB safety smoke wrappers.
  • Top-level service.py, db.py, and server.py import paths remain compatibility surfaces until a future approved REQ retires them.

Current Gaps / Planned Changes

  • Browser-level evidence exists locally and remains outside required CI gates by design.
  • Post-Phase-7 adapter narrowing is complete for the current compatibility architecture; deeper repository/use-case extraction and richer presenter/view-model layers remain future work.
  • Streamable HTTP MCP is now deployed for internal Synology operation. External exposure, reverse proxy/TLS/auth, and broader HTTP/REST adapter work remain deferred.

Update Triggers

  • Update this document when a command entry point changes.
  • Update this document when a runtime orchestration path changes.
  • Update this document when a batch changes the approved flow baseline.

Change Log

  • 2026-07-09 KST: REQ-021/BAT-017 기준으로 import provenance exposure flow, operator-summary handling, and explicit debug gate requirement를 반영.
  • 2026-06-26 22:24 KST: Created by bootstrap-baseline from repository observation.
  • 2026-06-27 10:17 KST: BAT-002/REQ-002 기준으로 운영 backup/status/list/hash 및 restore 제한 flow 추가.
  • 2026-06-29 KST: REQ-003/BAT-003 기준으로 statement-unavailable 수동 잔액대조 flow 추가.
  • 2026-06-29 KST: REQ-004/BAT-004 기준으로 Streamlit browser evidence capture flow 및 UI evidence gate 기준 추가.
  • 2026-06-29 KST: REQ-005/BAT-005 기준으로 dashboard operations hub 및 liquidity_bucket/last_balance 자산 유동성 flow 추가.
  • 2026-06-30 KST: REQ-006/BAT-006 기준으로 GitHub Actions CI validation gates, synthetic fixture DB boundary, AppTest/HTTP/DB safety smoke flow 추가.
  • 2026-06-30 KST: REQ-007/REQ-008/BAT-007 기준으로 contract-regression/lint CI required-check flow 추가.
  • 2026-07-03 KST: REQ-013/REQ-014/BAT-010 기준으로 service facade → application, db shim → infrastructure/sqlite, MCP/Streamlit adapter seam flow를 반영했다.
  • 2026-07-03 KST: REQ-016/REQ-017/REQ-018 및 BAT-012/BAT-013/BAT-014 기준으로 imports/advanced owning services, parser seam, MCP tool_contracts, Streamlit page/domain gateway flow를 반영했다.
  • 2026-07-07 KST: REQ-019/BAT-015 기준으로 Docker network MCP service flow와 legacy jarca DB → jarca-ledger volume migration flow를 추가했다.
  • 2026-07-08 KST: REQ-020/BAT-016 기준으로 review decision/reconciliation workbench persistence flow와 운영 허브 지표 집계를 추가했다.