Files
jarca-ledger-mcp/docs/project-structure.md
T

21 KiB

Project Structure — Dashboard 관리자 인증

목적과 경계

Issue #6 인증을 기존 Dashboard 구조에 배치하고 fail-closed 경계와 server-only secret binding을 유지한다.

  • 포함 경계: dashboard/ 인증 adapter/gate, tests, 운영 문서
  • 제외 경계: MCP transport, 금융 schema, DB migration, external auth middleware

디렉터리 구조

dashboard-source — Dashboard source

dashboard/
├── server.py
├── auth_server.py
├── authentication.py
├── app.py
├── common.py
└── page_views/
경로 종류 책임 공개 진입점 내부 구현 경계 편집 정책 생성 주체
dashboard/server.py source ASGI app 조립 app route wiring only source review required developer
dashboard/auth_server.py source login/cleanup/logout response create_auth_routes() no DB/page imports source review required developer
dashboard/authentication.py source config, constant-time compare, token verify, gate require_dashboard_authentication() server-only secret use source review required developer
dashboard/app.py source auth gate first, then DB path resolution, common shell/sidebar/refresh assembly, and target body renderer dispatch main() shell/background remain outside the replaceable body; no token signing details source review required developer
dashboard/common.py source shared Dashboard shell, menu/query transition, stable body container, loading/error/retry rendering, and app background/style render_sidebar_nav(), render_dashboard_body(), inject_app_css() no authentication transport or financial write orchestration source review required developer
dashboard/page_views/ source financial UI pages page_* functions no auth transport calls source review required developer

dashboard/common.py owns the shared visual theme through JARCA_COLORS, JARCA_PLOTLY_TEMPLATE, and inject_app_css(). Page renderers consume that theme but do not own or replace the authenticated shell/sidebar background.

verification-tests — 인증 검증

tests/
├── test_dashboard_authentication.py
├── test_dashboard_persistent_authentication.py
├── test_dashboard_auth_server.py
├── test_dashboard_menu_transition.py
├── test_streamlit_browser_evidence.py
└── test_dashboard_authentication_app.py
경로 종류 책임 공개 진입점 내부 구현 경계 편집 정책 생성 주체
tests/test_dashboard_authentication.py test credential compare, delay, redaction pytest tests test-only settings source change paired with test developer
tests/test_dashboard_persistent_authentication.py test claims, TTL, tamper, rotation pytest tests no real secrets source change paired with test developer
tests/test_dashboard_auth_server.py test HTTP routes and cookie scope pytest tests synthetic test credentials source change paired with test developer
tests/test_dashboard_menu_transition.py test REQ-002 menu/query/body transition and cache-clear regression pytest/AppTest synthetic fixture DB; no real secrets source change paired with test and browser evidence where required developer
tests/test_streamlit_browser_evidence.py test transition evidence manifest, redaction, TLS fixture and fail-closed validation pytest generated synthetic values only; no captured credential values evidence-harness change paired with test developer
tests/test_dashboard_authentication_app.py test gate ordering and cleanup/UI AppTest fixture DB only source change paired with test developer

browser-evidence — 실제 전환 관찰

경로 종류 책임 공개 진입점 내부 구현 경계 편집 정책 생성 주체
scripts/streamlit_browser_evidence.py verification tool synthetic DB와 runtime 생성 인증 설정으로 실제 HTTPS Dashboard 전환의 frame/DOM/document/shell 관찰을 수집하고 redacted manifest를 검증 --mode transition 운영 DB·credential 사용 금지; 성공 증거는 browser/server teardown 뒤에만 확정 source review and focused test required developer
docs/evidence/issue-9-dashboard-menu-transition/ evidence artifact exact source hash에 결합한 authenticated browser frame, screenshot, runtime, validator 결과 manifest.json synthetic fixture only; credential/token/cookie 값 금지 immutable after verification except complete regeneration verification runner

deployment-docs — 운영 문서

docs/requirements/req-001_dashboard-administrator-authentication.md
docs/requirements/req-002_dashboard-menu-transition.md
docs/evidence/issue-9-dashboard-menu-transition/
docs/interface-contract.md
docs/runtime-flow.md
README.md
deploy/k8s/README.md
경로 종류 책임 공개 진입점 내부 구현 경계 편집 정책 생성 주체
docs/requirements/req-001_dashboard-administrator-authentication.md requirement approved REQ-001 revision 2.0 REQ-001 canonical traceability update in place developer
docs/requirements/req-002_dashboard-menu-transition.md requirement approved REQ-002 revision 1.0 REQ-002 canonical traceability update in place developer
docs/interface-contract.md contract HTTP/cookie/gate contracts contract IDs no implementation secrets update with API changes developer
docs/runtime-flow.md design runtime states/transitions flow IDs no secret values update with flow changes developer
README.md operations local/deployment constraints operator commands no secret values operational review developer
deploy/k8s/README.md operations k3s secret/TLS procedure deployment procedure no secret values deployment review developer

의존 방향

출발 영역 대상 영역 허용 여부 규칙 공유 계약 위치
dashboard.server dashboard.auth_server 허용 compose ASGI routes only docs/interface-contract.md
dashboard.server dashboard.app 허용 app remains protected by gate docs/runtime-flow.md
dashboard.app dashboard.authentication 허용 gate precedes DB/page dispatch docs/interface-contract.md
dashboard.authentication dashboard.page_views 금지 auth module never imports financial pages docs/project-structure.md
dashboard.app dashboard.common 허용 menu/query/body transition helpers only after auth gate docs/interface-contract.md
dashboard.auth_server jarca_ledger_mcp DB 금지 login/cleanup/logout are DB-free docs/requirements/req-001_dashboard-administrator-authentication.md

변경 규칙

구분 규칙
새 모듈·파일 배치 auth route/gate changes stay in dashboard/; menu transition stays in existing dashboard.app/dashboard.common; no DB session module
이름·패키지 use existing dashboard package and snake_case modules
소스·테스트 대응 auth source behavior requires focused pytest/AppTest coverage; REQ-002 transition behavior requires focused pytest/AppTest targets and real-browser evidence where specified
생성 산출물 evidence may be redacted; never commit credentials, secrets, tokens, or cookie values

검증

  • 구조 검사 명령:

    python -m compileall -q dashboard tests scripts
    
  • 구조 검사 기대 결과: exit 0 and no generated source outside ignored bytecode locations

  • 정적 분석 명령:

    uv run --extra dashboard --extra dev ruff check dashboard tests scripts
    
  • 정적 분석 기대 결과: exit 0 with no diagnostics

  • 문서와 실제 트리의 정합성: every listed source/test/document path exists; dependency table has no forbidden reverse edge; REQ-002 symbols resolve to dashboard/app.py, dashboard/common.py, and named tests

REQ-003 additive structure

ledger-application — shared valuation and snapshot services

jarca_ledger_mcp/
├── application/account_valuation_service.py
├── application/assets_service.py
├── application/accounts_write_services.py
├── application/imports_service.py
├── application/reconciliation_service.py
├── infrastructure/sqlite/migrations.py
├── adapters/mcp/server.py
└── adapters/streamlit/{accounts_gateway.py,assets_gateway.py}
경로 종류 책임 공개 진입점 내부 구현 경계 편집 정책 생성 주체
jarca_ledger_mcp/application/account_valuation_service.py source validation, selection, idempotency, correction named valuation functions SQLite through shared db source review + focused tests developer
jarca_ledger_mcp/application/assets_service.py source preview, formula, close/correction preview_asset_snapshot_close, close_asset_snapshot snapshot transaction source review + focused tests developer
jarca_ledger_mcp/infrastructure/sqlite/migrations.py source schema 12 additive migration init_db, migrate_db no UI/MCP imports migration review developer
tests/test_account_valuations.py test valuation contracts pytest synthetic DB paired with source developer
tests/test_asset_snapshots.py test preview/close/report contracts pytest synthetic DB paired with source developer
docs/data-model.md canonical doc entity/schema authority document no secrets update with schema developer

의존 방향 추가

출발 영역 대상 영역 허용 여부 규칙 공유 계약 위치
dashboard.page_views streamlit gateways 허용 page → gateway only docs/interface-contract.md
streamlit gateways application services 허용 adapter delegates; no SQL docs/runtime-flow.md
MCP adapters application services 허용 tool delegates; no duplicate business logic docs/interface-contract.md
application services infrastructure.sqlite 허용 service → shared db/schema docs/data-model.md
application services dashboard 금지 no reverse UI dependency docs/project-structure.md

변경 규칙 추가

구분 규칙
새 모듈·파일 배치 valuation/snapshot logic stays in application; adapters remain thin; no direct SQL in page/MCP
이름·패키지 existing snake_case modules and service re-exports
소스·테스트 대응 every valuation/snapshot change paired with named synthetic tests and docs validator
생성 산출물 only redacted synthetic evidence; no credentials, cookie, token or actual account data

REQ-003 preservation inventory

REQ-001 auth gate, cookie/cleanup/logout and auth-before-DB; REQ-002 menu labels/order, query sibling preservation, stable shell/background and browser evidence remain in the preceding sections. Missing semantic items: 0. Ambiguous semantic items: 0.

REQ-003 canonical module ownership and regression map

경로 책임·실패 경계
jarca_ledger_mcp/application/account_valuation_service.py register/list/select/correct; principal mapping, source_ref identity, parent scope, idempotency and no-write conflicts
jarca_ledger_mcp/application/assets_service.py preview/close/report; valuation_date/age/carry, approval, correction, warnings/exclusions and atomic run
jarca_ledger_mcp/application/asset_account_services.py shared account/asset evidence and reconciliation boundary
jarca_ledger_mcp/infrastructure/sqlite/connection.py read_db() mode=ro and db_not_initialized without mkdir/migrate/commit
jarca_ledger_mcp/infrastructure/sqlite/migrations.py explicit init_db() and additive migration
jarca_ledger_mcp/application/monthly_settlement_service.py monthly read model; monthly_source_snapshot_id alias only, never persistence

Named transitions are valuation-01→valuation-02→valuation-03→valuation-04, close-01→close-02→close-03→close-04, prop-01→prop-02→prop-03, db-init-01, db-read-01, db-read-02, and write-first-use-01; named failures are valuation-fail, close-fail, prop-fail, db_not_initialized, conditional_approval_required, idempotency_conflict, and correction_conflict. auth-before-DB precedes all reads.

Regression tests are test_valuation_round_trip_preserves_null_zero_and_physical_amount_mapping, test_source_ref_is_account_scoped_evidence_identity_without_explicit_key, test_direct_correction_requires_matching_existing_parent_and_reason, test_investment_without_verified_valuation_and_without_opening_balance_is_incomplete, test_timeseries_and_monthly_expose_canonical_asset_provenance, and test_read_queries_missing_nested_db_return_stable_error_without_creating_path. D06 requires these names and actual paths/signatures, not marker prose.

D01 preservation matrix

item source evidence test evidence
schema 11 legacy rows infrastructure/sqlite/migrations.py: additive schema 12 migration tests/test_issue_12_regressions.py::test_schema12_migration_preserves_legacy_rows_indexes_and_is_idempotent
auth gate and cookie lifecycle dashboard/server.py: login, cleanup, logout, auth-before-DB gate tests/test_dashboard_authentication.py, tests/test_dashboard_persistent_authentication.py
REQ-002 menu labels/order dashboard/common.py: canonical 10-option menu and query transition tests/test_dashboard_menu_transition.py
MCP envelope and tools adapters/mcp/server.py: shared success/error response envelope and named tools tests/test_contract_regression.py
reconciliation and monthly read models application/reconciliation_service.py, application/monthly_settlement_service.py: read-only propagation tests/test_issue_12_review59_reports.py, tests/test_service.py::test_monthly_settlement_summary_read_model_foundation

Each row is an independently reviewable preservation claim: the source column names the canonical implementation boundary and the test column names executable evidence. A prose inventory without both references is not evidence.

D05 canonical ownership

concern owner boundary
monthly settlement monthly_settlement_service.py read-only monthly read model; monthly_source_snapshot_id aliases snapshot_run_id, never persistence
reconciliation reconciliation_service.py computes completeness/status and provenance; never creates fake transactions
policy assets_service.py owns exact/as-of, approval, exclusion/carry, correction and drift policy decisions
read-only assets_service.py preview/report path preview is no write: no insert, migrate, mkdir, or commit; explicit close is the write boundary
redaction adapters/report serializers only redacted evidence crosses output boundary; no credential/token/cookie/raw account data

The owner is the canonical decision or write boundary; consumers render or read its result and do not reimplement policy.

The Dashboard gateway is jarca_ledger_mcp/adapters/streamlit/overview_gateway.py (including get_asset_snapshot_report and reconciliation/monthly read delegates). It calls shared application read services after auth-before-DB; page rendering is not an alternate policy or persistence boundary. A missing DB has stable unavailable semantics (db_not_initialized) and no-create behavior. The missing DB stable unavailable contract is no-create. An initialized DB read failure is db_error; initialized read has no write, migration, mkdir, or commit. The initialized DB read failure is db_error and initialized read has no write.

Reconciliation ownership remains in reconciliation_service.py: opening evidence and transaction coverage are required inputs. Missing opening evidence or incomplete coverage produces INCOMPLETE_CALCULATION/reconciliation unavailable with provenance, never an inferred balance or fake transaction.

Issue #15 settlement draft ownership

Path Ownership / boundary
jarca_ledger_mcp/application/settlement_draft_service.py Shared business validation, frozen selection/review/approval/finalize; owns no UI or transport behavior.
jarca_ledger_mcp/application/monthly_settlement_service.py Read-only monthly aggregate; never draft mutation or transaction readiness write.
jarca_ledger_mcp/application/assets_service.py Existing close/report authority; draft finalization does not call live-select close as shortcut.
jarca_ledger_mcp/infrastructure/sqlite/migrations.py Additive schema 12→13 migration; schema initializer and migration constraints agree.
jarca_ledger_mcp/adapters/mcp/server.py Thin same-name/same-signature MCP tools; no duplicate business logic, no new auth claim.
jarca_ledger_mcp/adapters/streamlit/ Existing Dashboard gateway boundary; auth-before-DB, explicit user actions only.
tests/test_monthly_settlement_drafts.py Synthetic DB lifecycle, failure injection, replay and no-write regressions.

Never document invented jarca_ledger_mcp.mcp or monthly.py modules. transaction readiness is separate from asset completeness and monthly reads remain read-only.

Shared settlement-draft entrypoints

Path Responsibility / entrypoint and dependency boundary
jarca_ledger_mcp/service.py Existing public re-export facade exports the ten lifecycle operations from application/settlement_draft_service.py; adapters share these functions, not separate business implementations.
jarca_ledger_mcp/adapters/mcp/server.py Same-name MCP lifecycle tools delegate to the shared facade, retaining existing success/error envelopes.
jarca_ledger_mcp/adapters/mcp/tool_contracts.py Registers the same facade callables and their inputSchema contracts; internal db_path remains outside public MCP input.
jarca_ledger_mcp/adapters/streamlit/settlement_gateway.py Wraps shared lifecycle functions plus valuation list/register/correct delegates, preserving auth-before-DB and internal database-path resolution.
dashboard/page_views/settlement_drafts.py render_settlement_drafts owns reusable presentation and explicit user-action controls through the gateway; no direct SQL or duplicated approval policy.
dashboard/page_views/monthly_settlement.py page_monthly_settlement invokes the shared panel beside the existing read-only monthly summary.
dashboard/page_views/assets.py page_assets invokes the same panel beside existing valuation and immutable asset-history views.
jarca_ledger_mcp/application/account_valuation_service.py register_account_valuation, list_account_valuations, and correct_account_valuation retain registration, validation and append-only correction ownership; the draft service reuses their evidence.
jarca_ledger_mcp/application/assets_service.py Owns established valuation/amount authority and asset close/report semantics; draft finalization does not bypass review by calling legacy live-select close.
jarca_ledger_mcp/application/monthly_settlement_service.py get_monthly_settlement_summary owns read-only propagation of finalized evidence, not draft mutation or transaction-readiness writes.
jarca_ledger_mcp/infrastructure/sqlite/schema.py schema 13 initialization uses the additive migration path; no adapter owns persistence constraints.
jarca_ledger_mcp/infrastructure/sqlite/migrations.py Creates persistent draft/item tables and indexes, preserving existing schema and rows on repeated initialization.

Shared settlement-draft policies

  • jarca_ledger_mcp/application/settlement_draft_service.py checks one active draft per month for ordinary and correction drafts; SQLite independently enforces it with idx_settlement_drafts_active_month on month WHERE status='active'. Completed and cancelled history is retained, not deleted to release that slot.
  • The same application service validates strict month syntax and month-end basis-date equality. Dashboard and MCP cannot supply an alternate date policy.
  • The shared review service exposes unverified candidate_amount with authority amount NULL; no adapter may sum it as verified evidence. A confirmed child requires explicit reselection, fresh review and approval; correction children are not silently followed.
  • Dependencies remain page → gateway → public facade → application → SQLite, with MCP server/tool contracts → the same facade. No UI/MCP direct SQL, application-to-Dashboard reverse dependency or duplicated business validation is introduced.
  • Paired synthetic coverage: tests/test_monthly_settlement_drafts.py (month-end, active-month, unverified/reselection, cancellation and atomicity), tests/test_settlement_draft_adapters.py (facade/gateway/MCP signatures and no-create reads), tests/test_settlement_draft_dashboard.py and tests/test_settlement_draft_panel_workflow.py (shared panel/actions), tests/test_settlement_draft_mcp_runtime.py (real stdio responses), and tests/test_settlement_draft_docs.py (this mapping). Existing authentication/menu/legacy regression tests remain unchanged.