Files
jarca-ledger-mcp/docs/runtime-flows.md
T
Jarca 2ccfc9c064 feat: deploy jarca ledger network mcp service
- add Docker deployment for independent jarca-ledger container
- enable FastMCP streamable-http runtime configuration
- document dcy-013, REQ-019, and BAT-015 verification evidence
- update structure/runtime baselines and deployment runbook
2026-07-07 23:04:42 +09:00

159 lines
13 KiB
Markdown

# 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-07
- Source Discovery / Batch: bootstrap-baseline, BAT-006, BAT-007, BAT-008, BAT-010, BAT-012, BAT-013, BAT-014, dcy-013/BAT-015
- 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.
6. Hermes surfaces the tool result to the user or uses it in a follow-up workflow.
## 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 provenance, and records an import batch.
4. Reports and dashboard views read the inserted rows using shared category/cashflow semantics.
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: `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-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를 추가했다.