Skip to Content

Frame

한 줄 소개: 한국 회계기준(KSME · K-GAAP)을 따르는 복식부기 회계 백엔드. 법인마다 장부가 물리적으로 분리되고, 모든 쓰기는 되돌릴 수 없는 감사 로그로 남는다. 사람은 웹 화면으로, AI 에이전트는 MCP 93개 도구로 같은 장부를 다룬다.

주소

용도주소
MCP 엔드포인트https://frame.axelabs.ai/frame/mcp
운영 웹 UIhttps://frame.axelabs.ai/frame/
스키마 목록https://frame.axelabs.ai/frame/schemas

세 주소 모두 인증이 필요하다 — 로그인하지 않고 열면 401 이 돌아온다(브라우저는 로그인 화면으로 간다). 호스트 맨 주소 https://frame.axelabs.ai 는 /frame/ 으로 옮겨 준다.

고객 전용 인스턴스는 같은 호스트의 경로에 선다 — 웹 https://frame.axelabs.ai/t/<tenant>/frame/, MCP https://frame.axelabs.ai/t/<tenant>/frame/mcp. 입구는 모두에게 같다: 어느 경로로 들어와도 로그인한 계정의 테넌트가 화면을 정하고, 다른 테넌트의 입구로 들어온 사람은 로그인 직후 자기 자리로 옮겨진다(그 입구에서는 세션을 만들지 않는다). 인스턴스마다 쿠키 경로가 겹치지 않아 한 인스턴스의 세션이 다른 인스턴스로 실리지 않는다. 예전 주소 https://axe.axelabs.ai/frame/... 는 호환용으로 남아 MCP 커넥터는 그대로 쓰고, 브라우저 페이지는 frame.axelabs.ai 의 같은 경로로 옮겨 준다.

무엇을 하는가

  • 복식부기 장부 — 차변·대변이 맞지 않는 분개는 애초에 기재되지 않는다. 분개 등록은 다층 검증을 통과해야 커밋된다.
  • 개인정보 암호화 — 법인별 salt는 완성된 값만 원자적으로 확정하고 디스크 저장을 확인한 뒤 사용한다. 첫 접근이 동시에 일어나도 빈 salt를 읽는 경합을 막으며, 기존 salt를 덮어쓰지 않는다.
  • 법인별 격리 — 법인·펀드마다 별도 스키마. 한 법인의 조회가 다른 법인의 데이터에 닿지 않는다. 법인(corporate)과 펀드(개인투자조합·벤처투자조합)를 같은 평면에서 다룬다.
  • append-only 원장 — 원천 거래(입출금)와 분개 라인은 수정·삭제 권한 자체가 없다. 정정은 역분개로만 한다. 모든 쓰기는 감사 로그에 1행씩 남는다.
  • 원천 데이터 자동 적재 — 은행·카드·홈택스 등에서 받은 파일을 올리면 포맷을 자동 인식해 원천 거래로 적재한다. 한 번 인식한 포맷은 캐시되어 다음부터 즉시 처리된다.
  • 재무제표 4종 — 재무상태표 · 손익계산서 · 현금흐름표(간접법) · 자본변동표. 시산표는 임의 시점으로 조회할 수 있다.
  • 증빙 보관 — 모든 증빙은 내용 해시로 주소화해 보관하고, 분개에서 증빙까지 링크가 끊기지 않는지 정기적으로 검사한다.
  • 외부 재무 서비스 수집기 — AXE 법인과 고객 전용 인스턴스가 클로브의 공식 MCP에서 은행 거래·세금계산서를 받아 원천 행으로 적재한다. 조회 도구 이름 허용 목록과 법인별 고정 워크스페이스를 지킨다. 도구 목록 변경은 자동 비교하고, 쓰기 도구 변경과 호환되는 조회 도구 변경은 기록하며 계속한다. 조회 도구 삭제·쓰기 전환·비정상 도구 정의·인자 또는 응답 적재 계약 불일치면 멈추고 알린다. 응답의 필수값은 거래 ID·일자와 계좌 식별로 제한하며 선택 금액·통화·빈 목록은 기존 기본값으로 처리한다. AXE 세금계산서의 13자리 개인 식별번호는 저장 전에 마스킹하고, 승인번호 형식이 맞지 않으면 증빙 생성을 보류한다. 고객 증빙은 재현 계약에 따른 원문 보존 정책을 유지한다. 같은 기간의 재수신은 중복을 걸러 내고 회차별 건수·합계·잔액 흐름을 점검한다. AXE 법인의 카드 승인내역을 적재하며, 계좌별 전환 시점 이하 거래는 대조에 사용하고 해외 승인의 환산 차이도 제한된 범위에서 짝지어 처리한다. 전환 시점 이하에서는 이전 수집에 빠진 전액취소만 원승인과 연결해 추가하고, 원승인이 이미 분개됐으면 정정 필요를 표시한다. 모호한 카드 계좌와 검토가 필요한 취소는 보류하고 이슈로 남긴다. 현금영수증은 실제 응답으로 검토한 매핑에 따라 수집에 동의한 법인만 적재한다. 상호·메모 칸은 저장하지 않고, 식별번호가 개인 식별번호 형태이면 그 행을 보류하고 알린다.
  • AXE 롯데카드 수집 일원화 — 롯데 자체 스크래퍼는 비활성으로 유지하고 클로브 카드 적재로 일원화한다. 전환 시점 이하 거래는 해외 승인 환산 차이를 포함해 대조하고, 이전 수집에 없는 취소만 원승인에 연결해 보충한다. 이미 분개된 원승인은 정정 대상으로 표시하며, 해소된 보류와 경보는 자동으로 닫는다.
  • 고객 전용 인스턴스 옵션 — 외부 AI 호출 차단(양식 자동 판별·AI 분류를 쓰지 않는다), MCP 응답의 거래처·적요 가림, 그 고객 테넌트가 아닌 계정의 로그인·MCP 접근 차단. 기본은 모두 꺼져 있다. 고객 전용 외부 재무 서비스 수집기는 외부 AI 차단과 테넌트 차단이 켜진 인스턴스에서 돈다. AXE 법인 수집은 AXE 인스턴스에서 실행하며 이 두 스위치를 기동 조건으로 강제하지 않는다. 가림은 고객이 고르며 수집기의 조건이 아니다.
  • 결산 — 회계기간을 열고(open) → 가마감(soft close) → 확정(hard close) 으로 전이시킨다. 확정된 기간에는 기재가 막힌다. 전기 마감 잔액을 당기 기초로 이월한다.

쓰는 방법

표면대상내용
MCPAI 에이전트Claude 등 MCP 클라이언트에 커넥터로 등록하면 아래 93개 도구를 그대로 쓴다. 조회·기재·결산이 전부 도구로 노출된다.
운영 웹 UI사람브라우저에서 로그인해 회계기간·계정과목·거래처·세금계산서 정기 발급 스케줄을 직접 관리한다. 도구 호출이 어색한 운영 작업용. 실제 발급은 화면이 아니라 자동 실행기(워커)만 한다.
Export외부 회계법인시산표·총계정원장 등을 CSV/JSON 으로 내보낸다.

인증

Microsoft 계정으로 로그인한다. MCP 클라이언트는 커넥터 등록 시 표준 OAuth(PKCE) 흐름을 타고, 브라우저는 같은 계정으로 SSO 한다. 인증되지 않은 MCP 요청에는 401 과 함께 인가 서버 위치를 알려주는 표준 메타데이터가 돌아가므로, 클라이언트가 흐름을 자동으로 이어간다.

권한은 법인 × 스코프로 부여된다.

스코프할 수 있는 일
read조회 전반 (잔액·시산표·재무제표·분개·증빙·거래처)
write분개 기재·역분개, 파일 적재, 증빙 등록, 거래처·계좌 관리
close마감 미리보기·확정, 기간 전이, 기초 이월, 거래처 병합
reopen이미 소프트클로즈된 기간에 다시 기재하기 — post_journal·reverse_journal 의 allow_soft_closed 를 실제로 허가하는 스코프
admin법인 등록, 계정과목 신설·수정·삭제, 회계기준 정책 관리

고객 전용 인스턴스는 그 고객 테넌트의 계정만 받는다 — 다른 테넌트 계정은 MCP 에서 TENANT_MISMATCH, 웹에서는 로그인 거부(AXE 운영자는 인스턴스의 허용 목록으로만). 같은 인스턴스는 외부 재무 서비스 수집기의 회차마다 받은 건수·적재 건수·점검 결과를 법인 장부 안의 회차 기록으로 남기고, 수집기는 운영자 CLI 명령 하나(1회 또는 상주 루프)로 돈다.

앞의 셋은 위가 아래를 겸한다(close 를 가지면 read·write 도 된다). reopen 과 admin 은 그 사다리 밖이라 토큰에 그 이름이 그대로 있어야 하고, close 나 admin 이 reopen 을 대신 서지 못한다. 그래서 write 만 든 호출자가 allow_soft_closed=True 를 넘기면 기재가 아니라 SCOPE_INSUFFICIENT 를 받는다 — 그 인자는 호출자가 채우는 불리언이라, 인가가 평범한 write 뿐이면 write 스코프 하나로 소프트클로즈된 기간이 열린다.

CLI

명령동작·실패 의미
frame migrate공용 스키마와 등록된 법인·펀드 스키마를 마이그레이션한 뒤, 등록 누락·미스탬프 스키마를 포함한 모든 frame 엔티티 스키마가 실행 이미지의 최신 리비전(head)인지 확인한다. 하나라도 일치하지 않으면 실패하며 entity schema(s) not at entity head ... 와 대상 스키마·Fix: 안내를 출력한다. 등록 누락·미완료 또는 이미지와 DB 리비전 불일치를 안내에 따라 해소한 뒤 재실행한다. 법인 등록과 같은 잠금을 사용하므로 등록 중이면 완료까지 기다린다.
frame clobe-seal-buyer-no --entity <고객 법인> [--apply]이미 적재된 클로브 세금계산서의 13자리 공급받는자 번호(주민·법인등록번호 형태)를 적재 단계와 같은 모양(법인 PII 키의 암호문)으로 바꾸는 1회 정리. 기본은 세기만 한다. --apply 는 한 트랜잭션에서 증빙·감사 기록·원천 응답 파일을 바꾸고, 원문이 남았거나 깨끗함을 증명할 수 없는 곳(못 읽거나 없는 원천 파일, 다른 법인이 함께 가리키는 파일)이 있으면 전부 되돌린다. 출력은 건수만이다. 저장소를 공유하는 어느 법인이든 수집기 회차 중이면 실패한다 — 회차 사이에 다시. AXE 법인은 대상이 아니다(적재 단계 가림).

환경 변수

frame 스택의 망 구성과 원본 저장소 설정이다. 비밀값이 아니므로 컨테이너·호스트 환경에 평문으로 둔다.

이름의미기본값언제 바꾸나
FRAME_WEB_MOUNTED_PREFIX이 인스턴스의 웹·MCP 경로 접두. /frame(기본) 또는 /t/<tenant>/frame 만 허용 — 그 밖이면 기동하지 않는다. 쿠키 경로·로그인 콜백·MCP 리소스가 모두 이 값을 따른다./frame고객 전용 인스턴스를 같은 호스트의 경로에 세울 때
FRAME_WEB_PUBLIC_BASE_URL웹의 공개 오리진(로그인 콜백·정본 링크의 앞부분).https://axe.axelabs.ai웹 정문 호스트를 바꿀 때
FRAME_WEB_LEGACY_HOSTS옛 공개 호스트(쉼표 구분). 그 호스트로 온 브라우저 페이지 열람(GET/HEAD)만 공개 오리진의 같은 경로로 302 한다. MCP·메타데이터·JSON 요청은 옮기지 않는다.비움웹 정문을 옮긴 뒤 옛 주소를 받을 때
FRAME_TENANT_HOMES다른 테넌트의 자리 표(JSON {tenant: 경로}). 값은 그 테넌트의 접두(/frame 또는 /t/<tenant>/frame)여야 하고 자기 자리를 가리킬 수 없다. 로그인한 계정의 테넌트가 표에 있으면 세션 없이 그 자리로 옮긴다.비움같은 호스트에 인스턴스를 더할 때
FRAME_MCP_PUBLIC_BASE_URLMCP 리소스의 공개 오리진(https://<host> 만). 비우면 기존 주소 그대로.비움고객 전용 인스턴스의 MCP 를 서비스 호스트에서 받을 때
FRAME_CLOBE_TOKEN_FILE회전 토큰 파일의 영속 디렉터리 내 위치. 두 배포 색이 같은 파일을 공유한다.AXE: 영속 볼륨 안의 토큰 파일(경로는 운영 문서)토큰 영속 마운트를 바꿀 때
FRAME_CLOBE_ACTIVE_ALIAS클로브 루프의 활성 배포 색을 판정하는 네트워크 alias. 1회 실행에는 적용하지 않는다.AXE: frame-clobe-worker워커 alias를 바꿀 때
FRAME_CLOBE_CASH_RECEIPT_ENTITIES현금영수증 수집에 추가로 동의한 법인 목록(쉼표 구분). 응답 매핑은 실측으로 검토해 고정했다.비움(모든 법인 기본 off)법인이 현금영수증 수집에 동의했을 때
FRAME_CLOBE_CARD_ENTITIES카드 수집의 코드 기본 목록에 더할 법인 목록(쉼표 구분). 추가 법인도 응답 매핑 검토가 필요하다.비움(AXE axec·axev 기본 적재 활성; 전환 이후만 적재, 모호·취소 검토 건 보류)매핑 검토 후 법인을 추가할 때
FRAME_FILE_STORAGE_PATH원본 파일 저장소. 절대경로이며 쓰기 가능한 영속 마운트 안에 있어야 한다. MCP·worker·invoice-worker는 기동 시 검사한다./app/.local/files저장소 마운트 위치를 바꾸는 배치에서만
FRAME_ALLOW_EPHEMERAL_STORAGE1이면 영속 마운트 검사를 생략한다(절대경로 요건은 유지). 개발·테스트 전용이며 운영에서는 금지.0로컬 개발·일회용 테스트에서만
FRAME_TRUSTED_PROXIES앱(blue/green)이 X-Forwarded-For · X-Forwarded-Proto 를 믿어 줄 피어 주소 집합. 콤마로 구분한 IP 또는 CIDR 이고, 목록 밖 피어가 붙여 보낸 forwarded 헤더는 무시된다.비우거나 미설정이면 loopback(127.0.0.1 · ::1) + RFC1918 세 대역. 셀프호스트 compose 는 이 값을 리버스 프록시 홉 전용 네트워크(frame_edge)의 서브넷 하나로 좁혀서 준다앞단 프록시가 그 홉 밖에 있는 배치일 때만
FRAME_PROXY_TRUSTED_RANGES앞단 Caddy 프록시의 trusted_proxies — 상류가 붙여 보낸 forwarded 헤더를 그대로 통과시킬 소스 대역. 그 밖에서 들어온 요청의 헤더는 종전대로 프록시가 덮어쓴다.Caddyfile 기본값 private_ranges(loopback + RFC1918). 셀프호스트 compose 는 여기에도 같은 frame_edge 서브넷을 준다위와 같음
FRAME_SCRAPE_INGEST_URL미니 호스트의 스크래퍼(frame scrape-due, launchd)가 다운로드한 파일을 어디에 적재하느냐. 비우면 종전대로 호스트의 로컬 파일저장소 + DB 직결. 클라우드 frame-mcp 의 MCP URL(https://axe.axelabs.ai/frame/mcp)을 주면 파일을 MCP 도구 ingest_file_blob(parser=<source_key>) 로 보내 행(RDS)과 blob(EC2)이 한 곳에 모인다. 전송 토큰은 호스트가 이미 가진 frame 토큰 서명 비밀로 그 자리에서 발급(10분·해당 법인 write) — 클라우드가 검증하는 같은 비밀이라 별도 보관·회전 없음. 전송 실패분은 .local/scrape-outbox/<source>/<entity>/ 에 남아 다음 틱이 브라우저 없이 재전송한다(서버가 거부한 파일은 옆에 .err 를 남기고 하루 한 번만 재시도). 이미 내려받은 파일을 손으로 보내려면 frame scrape-resend <파일…> --entity axec --source lottecard(파일 보존, 같은 바이트면 서버가 duplicate 로 답하며 blob 만 채운다 — 컷오버 전 미니에만 남은 blob 의 백필 경로).비움(로컬)웨이브 8 이후 미니 .env 에 한 줄. 스크래퍼가 클라우드 DB 를 볼 때(FRAME_DB_HOST 가 RDS 포워드) 반드시 함께 켠다 — 안 켜면 split-brain

두 값이 말하는 것은 같은 체인의 앞뒤 홉이다. 프록시가 믿는 대역이 상류 홉을 덮지 못하면 프록시가 상류의 X-Forwarded-Proto 를 스푸핑으로 보고 버린 뒤 자기 평문 리스너의 스킴으로 덮어쓰고, 앱이 믿는 집합이 프록시 홉을 덮지 못하면 앱이 프록시가 붙인 그 헤더를 아예 보지 않는다 — 어느 한쪽만 자기 앞 홉을 놓쳐도 리다이렉트가 평문으로 나가고 Secure 쿠키가 붙지 않아 로그인이 이뤄지지 않는다. 실제로 났던 회귀가 그 두 모양이다: 프록시 설정에 신뢰 선언이 아예 없었고, 앱은 웹 서버 기본값이 loopback 하나뿐이라 컨테이너 네트워크로 들어온 프록시를 신뢰하지 못했다. 지금은 양쪽 기본값이 그 홉을 덮으므로 두 변수를 비워 둔 배치에서도 서고, 변수는 기본값을 통째로 대체한다 — 배치마다 믿어야 할 프록시가 다르기 때문이며, 셀프호스트 compose 는 그것으로 신뢰를 홉 하나로 좁힌다. 닫히지 않는 것도 적어 둔다: 프록시가 게시한 포트로 들어오는 요청의 소스 주소는 언제나 그 홉의 게이트웨이라 프록시는 터널과 호스트-로컬 피어를 구별하지 못하고 그 헤더를 그대로 넘긴다 — LAN·tailnet 피어는 프록시와 앱의 호스트 포트를 loopback 에만 묶어 닫고, 이 두 값이 닫는 것은 앱 직행 위조이며, 호스트-로컬까지 닫으려면 터널이 frame_edge 에 직접 붙어 그 주소 하나만 신뢰해야 한다(전용 인입 홉 = B-frame-edge-dedicated-ingress-hop).

외부 요청은 터널 → 프록시 → frame 순으로 오고 마지막 홉이 컨테이너 네트워크라, frame 이 보는 피어는 loopback 이 아니라 프록시 컨테이너의 주소다. 그 주소가 이 집합에 없으면 forwarded 헤더가 버려져 리다이렉트의 Location 이 https 에서 http 로 강등되고(트레일링 슬래시 리다이렉트에서 실제로 났던 증상), 로그인 감사 줄에 실제 클라이언트 IP 대신 프록시 주소가 남는다.

반대로 아무 피어나 믿게 두면 두 값이 요청자 선택값이 된다 — 감사 로그의 IP 도, 모든 리다이렉트의 스킴도. 그래서 신뢰를 주소가 아니라 소속으로 정의한다. frame_edge 는 리버스 프록시와 MCP blue/green 만 올라가는 전용 네트워크이고 서브넷이 compose 에 못박혀 있어 셀프호스트 배치가 두 변수에 주는 값이 그 네트워크를 글자 그대로 가리킨다(셋이 어긋나면 테스트가 잡는다). 프록시는 이 네트워크에만 붙어 있으므로 신뢰 집합에 드는 홉은 그것 하나뿐이다. frame 워커와 blueprint 는 종전 기본 네트워크로 같은 이름의 MCP 에 계속 닿지만, 그 홉의 주소는 이 서브넷 밖이라 그들이 보낸 forwarded 헤더는 무시된다 — 브라우저가 아니라 Bearer 토큰 API 클라이언트라 잃는 것이 없고, 대신 감사 IP 와 리다이렉트 스킴을 그들이 정할 수 없게 된다.

/health 응답에는 forwarded_proto 필드가 있다 — 신뢰하는 프록시가 보낸 X-Forwarded-Proto 를 앱이 실제로 반영했는지 배포 검증에서 확인할 수 있도록, 그 요청에 대해 해석된 스킴(https 또는 http)을 그대로 보고한다. 운영자 CLI 의 frame 스왑은 컷오버 뒤 프록시를 거쳐 이 값이 https 인지 확인한다.

로그인 경로 점검 /frame/health/sso 은 인증 없이 실제 로그인과 같은 코드로 플랫폼 로그인의 토큰 교환과 서명키 조회를 시험해, 둘 다 되면 200·하나라도 막히면 503 을 돌려준다(결과는 60초 캐시, 비밀·주소·오류 문구는 싣지 않는다 — D-ops-120).

AXE 클라우드 배치는 compose 를 운영자 CLI 가 생성해 frame_edge 도 이 두 변수도 없다 — 거기서는 코드·파일 기본값(loopback + RFC1918)이 그대로 서서 프록시가 계속 신뢰받는다. 기본값을 홉 서브넷으로 좁히지 않는 이유가 그것이다: 기본값이 착지할 수 있는 위상보다 좁으면 그런 배치가 조용히 자기 프록시를 불신하게 되고, 좁히기는 좁은 위상을 실제로 가진 compose 가 준다.

상태 점검

경로의미
/health프로세스 생존 확인. DB가 응답하지 않아도 200이므로 서비스 준비 여부는 아래 경로로 확인한다.
/health/readyDB 연결까지 확인. 성공하면 200, 실패하면 503.

두 응답 본문의 slot은 응답한 배포 색(blue 또는 green)이다. 엣지에서도 어느 색이 응답했는지 구별할 수 있으며, 색을 지정하지 않은 단일 컨테이너·로컬 실행에서는 null이다. /health/ready의 503 응답에도 slot이 포함된다.

MCP 도구 93개

조회 — 잔액·재무제표

도구스코프설명
query_balanceread단일 계정의 시점 잔액
query_trial_balanceread현재 시산표 — 잔액이 있는 전 계정을 돌려주며(폐지된 is_postable=false 계정은 retired: true 로 표기하되 잔액은 숨기지 않는다 — 판정 기준은 포스팅과 같은 as_of_date 가 속한 정책 시대(명시 policy_id 우선)이며 그 시대에 없는 계정코드도 retired: true; 레거시 only_postable=true 는 구 leaf-only 필터를 그대로 재적용한다, DEPRECATED) 응답에 total_debit · total_credit · is_balanced 를 동반한다. is_balanced=false 는 원장 결함이다.
trial_balance_atread특정 시점 시산표 (검증용)
trial_balance_exportread전 계정 차변·대변 양변 내보내기
balance_sheetread재무상태표 (상위 계정 롤업)
income_statementread손익계산서
cash_flow_statementread현금흐름표 (간접법). 활동 분류가 완전하면 검증 플래그가 참으로 오고, 분류 못 한 계정은 따로 표시된다
equity_changes_statementread자본변동표
cap_table_atread시점별 캡테이블 snapshot — shareholding_event 합산으로 총주식수·주주별 지분율·주식종류별 집계 재구성 (as_of_date 기준)
simulate_roundread라운드 희석 시뮬레이션 — DB 기록 없는 순수 계산. pre-money·투자자별 신규 투자금·옵션풀 목표비중(pre-money carve-out, P = kS/(1−k) 대수해)으로 주당가격·신주·post 지분율·주주별 희석폭 산출
shareholder_register_docread주주명부 markdown 생성 — 마스킹된 주민/사업자번호만 사용(평문 PII 미노출), 주식종류·지분율·합계 표 포함
upsert_shareholderwrite주주 등록/수정 — (entity_id, name) 기준 upsert 라 같은 이름으로 다시 부르면 중복 없이 그 행을 갱신한다. 주주명부 ingest 가 만드는 것은 이 주주 행까지다
add_shareholding_eventwrite지분 변동 이벤트 1건 append — cap_table_at 이 이 이벤트들을 합산한다. shares_delta 는 부호 있는 값(처분은 음수), effective_date 를 생략하면 event_date 와 같다. event_kind 가 허용 enum 밖이거나 shares_delta 가 0 이거나 effective_date 가 event_date 보다 앞서면 INVALID_SHAREHOLDING_EVENT 로 거부. ingest 는 이벤트를 만들지 않으므로 유상증자·CB전환 반영은 이 도구로 한다
general_ledgerread총계정원장 — 계정별 거래 + 누계. counterparty_id 로 그 거래처가 걸린 라인만(거래처별 보조부), hide_reversals=true 로 검증된 원본+역분개 쌍을 양쪽 다 숨겨 살아있는 항목만 볼 수 있다(기본 false)
vat_summaryread부가세 신고 지원 집계 — 기간 × 법인의 매출세액·매입세액·차액. 라인 집계이지 최종 납부세액이 아니다 (의제매입·신용카드·대손 공제 미반영)

조회 — 분개·거래·증빙

도구스코프설명
list_journalsread분개장 목록. hide_reversals=true 로 검증된 원본+역분개 쌍을 양쪽 다 숨긴다(기본 false)
get_journalread단일 분개 상세 (라인 + 출처 링크)
journal_listingread분개 리포트
list_raw_transactionsread원천 거래(은행 입출금 등) 목록. 페이지네이션 상태를 함께 반환한다
search_evidenceread증빙 전문 검색. 세금계산서는 공급받는자 사업자번호(buyer_biz_no)를 숫자 10자리일 때만 싣는다 — 개인 발행분(13자리)은 비운다
list_open_itemsread미결 항목
list_periodsread회계기간 목록
list_sub_entitiesread자회사·펀드 등 하위 entity
list_entity_membersread그 entity 에 접근하는 사람 목록 — 명시 매핑된 이메일과 각자의 역할, 도메인 단위 허용. 읽기만 하며 권한을 바꾸지 않는다

조회 — 결의서·고정자산·급여

도구스코프설명
list_resolutionsread결의서 목록
get_resolutionread단일 결의서 상세 (연결된 분개 포함)
query_effective_resolutionsread특정 시점에 유효한 결의서
list_fixed_assetsread고정자산 목록
query_asset_book_value_atread고정자산의 시점 장부가액
list_pending_payrollread대기 중인 급여 지급 건

기재 — 분개

도구스코프설명
post_journalwrite분개 등록. 다층 검증 통과 시에만 커밋. 원천 거래가 정확히 하나로 특정되면 거래처를 규칙에 따라 자동 태깅한다 (명시값이 항상 우선)
reverse_journalwrite역분개 — 반대 분개를 새로 만들고 원본을 reversed 로 표시한 뒤 서로 링크한다. 이미 회수된 매출채권을 다시 살리는 방향의 역분개는 산술 불변식으로 거부한다. 다른 전표의 역분개(counter-entry)는 다시 역분개할 수 없다(REVERSAL_CHAIN_FORBIDDEN) — 되살리려면 post_journal 로 신규 전표를 친다 원 전표에 걸린 결의 중 역분개 일자에 유효한 것(status=effective, effective_from ≤ 일자 ≤ effective_until)만 역분개에 이어받아(link_reason = "inherited from reversed journal #N") 결의 필수 규칙을 원 전표와 같은 근거로 충족한다 — 이어받을 유효 결의가 없으면 종전처럼 거부되고, 취소·대체·만료 결의는 이어받지 않는다(도구 시그니처 불변, frame#48).
relink_reversalwrite수동으로 만든 반대 분개를 원본과 사후 연결. 계정별 순액이 0 이 아니면 거부. 새 분개를 만들지 않는다. 원본의 기간이 닫혀 있으면 거부한다 — 상태와 역분개 링크가 둘 다 원장이라 되열고 다시 부른다
flag_uncertaintywrite판단이 필요한 건을 미결로 올린다
resolve_open_itemwrite미결 해결
update_conversation_contextwrite미결에 붙은 대화 맥락 갱신
reconcile_and_proposewrite대사 후 분개 제안

기재 — 적재·증빙

도구스코프설명
ingest_file_blobwrite파일을 인라인(base64, content_base64) 또는 샌드박스 상대경로(source_path)로 올려 원천 거래로 추출 — 둘 중 정확히 하나. source_path 는 운영자가 읽기 전용 샌드박스 디렉터리를 설정한 인스턴스에서 승인된 워크로드 주체만 쓸 수 있고(..·절대경로·심볼릭 링크·빈 파일 거부, 256 MiB 상한), 설정이 없으면 거부된다(기본). 같은 바이트는 어느 모드로 보내도 같은 요청으로 취급된다(멱등 키·충돌 판정이 내용 기준). filename 이 source_file 의 원본 파일명·storage_url 에 그대로 남는다. 선택 인자 parser — lottecard 면 롯데 법인카드 CP2 승인내역 고정컬럼 파서(법인전체 export 를 카드별 계좌로 분배, 호스트 스크래퍼와 같은 파서)로 보내고 응답이 cards[]·raw{inserted,skipped,duplicate}·file_status; lottecard_statement 면 롯데카드 청구명세서 파서 — 머리글·카드번호를 먼저 검증해 양식이 다르거나 다른 카드 행이 섞이거나 카드가 기존 계좌 둘 이상에 맞으면 아무것도 쓰지 않고 거부한다. 승인내역 스크래퍼 행과 승인번호가 같은 경우에만 같은 거래로 인정해 다시 넣지 않고(짝은 검토 항목에 기록해 같은 행이 두 번 짝지어지지 않음), 승인번호가 같은데 날짜·금액·방향이 엇갈리거나(거래일 ±45일 안) 승인번호 없는 행이 같은 날·금액의 스크래퍼 행과 겹치면 넣지 않고 검토 항목(open_item, 태그 card-dedup)으로 보류한다 — 보류된 행은 다시 보내도 자동 적재되지 않는다. 같은 계좌의 적재는 서로 직렬화된다. 응답 raw 에 held·open_item_ids 가 붙는다. 생략 = generic 파이프라인. 같은 바이트를 다른 filename/parser 로 다시 보내면 IDEMPOTENCY_CONFLICT. 이미 행이 있는 파일을 다시 보내면 duplicate 를 돌려주되 blob 은 저장한다(행만 있고 blob 이 없는 상태의 치유)
ingest_file_localwrite허용된 디렉터리의 파일 경로로 추출 (대용량 파일용)
register_evidence_blobwrite증빙 등록 — 파일은 content_base64 또는 source_path 중 하나(ingest_file_blob 과 같은 규칙)
promote_source_file_to_evidencewrite적재 단계에서 거부된 파일을 증빙으로 승격
register_resolutionwrite결의서 등록
link_journal_to_resolutionwrite분개 ↔ 결의서 연결
update_resolution_evidencewrite결의서의 증빙만 사후 교체. 결의 본문·상태·연결 분개는 불변이고, 교체 이력은 결의에 누적된다

기재 — 전자(세금)계산서 발행 (볼타)

매출 전자(세금)계산서를 발행대행사 볼타(Bolta)의 API 로 정발행하고, 국세청 승인번호가 나오면 증빙과 분개(미수금 / 매출 / 부가세)를 장부에 자동으로 남긴다. 순서는 항상 미리보기 → 발행 → (필요하면) 재확인이다. 라이브 발행은 되돌릴 수 없고 정정은 수정발행으로만 한다(frame 미지원 — 볼타 대시보드).

  • 키는 법인마다 live(실발행)와 test(샌드박스)를 따로 둔다 — FRAME_BOLTA_API_KEY_<법인> / FRAME_BOLTA_TEST_API_KEY_<법인>, 값은 vault 에서 주입. 호출자가 mode 를 명시하면 그 슬롯의 키만 쓰고, 다른 법인·다른 mode 키로 넘어가지 않는다.
  • 이중 발행을 막는다. 같은 요청은 같은 관리번호로 보내고, 보내기 직전 발행 의도를 장부에 기록하며, 이미 보낸 요청과 같은 내용이면 볼타 키나 서버 비밀이 바뀌었어도 다시 보내지 않는다. 결과가 확정되지 않은 건은 재발행이 아니라 재확인(sync_tax_invoice)만 안내한다.
  • test 키 결과는 실제 법인 장부에 기록하지 않는다. 작성일자 기간이 닫혀 있으면 증빙만 남기고 분개는 보류한다(기간을 연 뒤 재확인하면 분개).
도구스코프설명
preview_tax_invoiceread발행 미리보기 — 부작용 없음. mode 기본값 test. 입력 정규화·세액 규칙(과세는 생략 시 공급가액의 10%, 직접 주면 ±1원까지)·사업자번호 검증·공급자=해당 법인 확인·기간/계정 사전 검사·볼타 발행 마감일과 발급자 확인 → 요청 본문과 preview_token 을 돌려준다. 같은 내용이 이미 발행 요청됐으면 경고. 선택 인자 revenue_account_code(기본 4101)로 분개할 매출계정을 지정하면 그 계정이 계정표에 있는지도 미리 검사한다 — 정기 발행 스케줄의 회차를 사람이 직접 발행할 때는 스케줄과 같은 계정을 준다
issue_tax_invoicewrite정발행. preview_token 과 mode 필수 — 미리보기와 다르면 보내지 않는다. 승인번호가 나오면 장부에 기록하고, 아직이면 pending_approval 을 돌려준다. 결과 미확정 오류(TAX_INVOICE_SUBMITTED_UNCONFIRMED · TAX_INVOICE_OUTCOME_UNKNOWN)에는 재발행하지 말고 재확인할 것. 선택 인자 revenue_account_code(기본 4101, 미리보기와 같은 값)는 발행 기록과 증빙에 남아, 나중에 재확인이나 홈택스 목록 적재로 분개해도 같은 계정으로 간다. 장부에 기록되는 발행이면 같은 거래처·같은 작성월을 정기 발행 스케줄 회차가 이미 발행했거나 발행 중일 때 거부한다(TAX_INVOICE_SCHEDULE_CONFLICT, 볼타에 보내지 않음) — 별개 공급임을 사람이 확인했을 때만 선택 인자 confirm_not_schedule_duplicate=true 로 발행하고, 그 확인은 발행 기록에 남는다
sync_tax_invoicewrite승인 대기·오류 건 재확인 → 승인번호가 나오면 장부 기록. mode 필수, issuance_key 또는 client_reference_id. 재실행해도 한 건만 남는다 — 홈택스 목록을 나중에 적재해도 승인번호로 중복을 걸러 낸다

기재 — 정기 발행 스케줄 (볼타)

매월 같은 거래처에 같은 내용으로 발행하는 매출 전자(세금)계산서를 스케줄로 등록하면, 실행기가 회차마다 위 볼타 발행과 같은 경로(미리보기 → 발행 → 재확인)로 발행하고 장부에 기록한다. 순서는 초안 생성(미리보기) → 사람이 승인 → 회차 자동 발행이다. 라이브 스케줄은 승인 후 자동 발행되며 되돌릴 수 없다(정정은 수정발행 — frame 미지원).

  • 작성일은 스케줄마다 규칙으로 정한다 — 예: 매월 25일(휴일이면 전 영업일), 매월 1일(휴일이면 다음 영업일). 달에 없는 날은 말일로, 휴일 이월은 작성월 안에서만 한다. 휴일은 토·일과 frame 에 내장된 관공서 공휴일 달력(설·추석·대체공휴일·선거일 포함, 매년 다음 해 월력요항이 나오면 갱신)이다. 달력이 아직 없는 해의 회차는 “토·일만 반영했다”고 경고하고, 그 해 달력이 등록되면 작성일이 공휴일에 걸린 회차를 알려 준다 — 작성일을 자동으로 옮기지는 않는다(승인 때 본 날짜가 모르게 바뀌지 않게). 새로 지정된 임시공휴일은 운영자가 설정으로 더한다.
  • 계약 만료일(valid_until)은 필수이고(한 스케줄은 최대 36개월), 만료일 이후 작성일의 회차는 만들지도 발행하지도 않는다. 자동 연장은 없다 — 만료가 다가오면 갱신 확인 알림이 뜨고, 사람이 갱신을 승인해야 다음 기간이 이어진다. 갱신하지 않으면 만료일 다음 실행에서 스케줄이 종료된다.
  • 첫 회차는 기본으로 작성일이 오늘 이후인 달부터다. 이미 지난 달은 홈택스에서 직접 발행했을 수 있으므로 시작 달(start_period)을 명시해야만 포함한다.
  • 이중 발행을 막는다. 회차(스케줄 × 작성월)마다 한 번만 발행하고, 같은 거래처·같은 작성월의 매출 계산서가 이미 장부에 있으면(홈택스에서 직접 발행한 경우 등) 발행하지 않고 확인을 요청한다. 결과가 확정되지 않은 회차는 재발행하지 않고 재확인만 한다.
  • 같은 거래처(같은 사업자번호)에 기간이 겹치는 스케줄은 만들 수 없다 — 정말 별개 용역이면 겹치는 스케줄을 별개로 선언해야 하고, 그 선언도 승인 대상이다. 다른 스케줄이 이미 발행한 같은 달 계산서도 중복 후보로 본다.
  • 다른 스케줄(종료한 스케줄 포함)이 같은 거래처·같은 달을 이미 발행했거나 발행 중(국세청 승인 대기 등)이면, 그 달을 덮는 새 스케줄의 생성·갱신·승인을 거부하고 발행 직전에도 다시 확인해 발행하지 않는다. 종료한 스케줄이라도 이미 보낸 계산서는 결과가 확정되면 발행되기 때문이다 — 발행 중인 달은 별개 용역 선언으로도 풀리지 않는다.
  • 스케줄 밖에서 직접 발행한 계산서와도 서로 막는다. 같은 거래처·같은 달을 직접 발행했는데 아직 국세청 승인 전이면 그 달을 덮는 스케줄을 만들거나 승인하지 않고 그 회차도 발행하지 않는다(재확인으로 확정한 뒤 판단). 반대로 스케줄 회차가 이미 발행됐거나 발행 중인 달을 직접 발행하려 하면 거부한다 — 별개 공급(추가 1회성 청구 등)임을 확인했을 때만 확인 표시와 함께 발행되고, 그 확인은 기록에 남는다.
  • 이자처럼 세금계산서 대상이 아닌 거래는 스케줄로 만들 수 없다. 공급시기 전 발행(선발행)은 계속적 용역에만 옵션으로 허용하고, 선발행한 계산서의 작성일자는 발행일이다(미래 날짜로 발행하지 않는다).
  • 일시정지했다가 재개하면, 정지 중 발행 시점이 지난 회차는 자동 발행하지 않고 승인을 기다린다(용역을 공급하지 않은 달은 발행하면 안 된다). 단 발행 시점이 재개 뒤인 회차는 정지가 그 달 일부에 걸쳤어도 보류하지 않는다 — 자동 승인 스케줄이면 원래 금액 그대로 발행되니, 일할 청구가 필요하면 발행 전에 그 회차 금액을 조정하거나 건너뛴다(재개 결과가 그 회차를 알려 준다).
  • 스케줄을 종료한 뒤에 남은 미발행 회차(종료 순간 발행이 멈춰 있던 회차 등)도 실행기가 취소하고, 작성일이 지났으면 직접 발행 여부를 확인하라는 알림을 남긴다 — 공급한 달이 조용히 미발행으로 남지 않게.
  • 알림(승인 대기·발급 기한 임박·실패·만료 임박·실행기 오류)은 미결(list_open_items)로 남는다. 한 스케줄이 연속으로 실패하거나, 실패를 기록하는 것조차 실패하면 실행기 상태도 비정상으로 보고된다.
  • 무중단 배포(두 슬롯 동시 운영) 중에는 트래픽을 받는 슬롯의 실행기만 발행한다 — 이전 슬롯의 실행기는 대기한다(수정 배포 뒤 옛 코드가 발행을 계속하지 않게). 대기 중인 실행기는 발행할 일이 있는데 어느 슬롯도 제때(기본 90분 안에) 실행하지 않으면 비정상으로 보고하고 미결 알림을 남긴다 — 두 슬롯 모두 대기하는 설정 오류가 조용히 미발행으로 남지 않게.
도구스코프설명
create_invoice_schedulewrite정기 발행 스케줄 초안 생성 — 아직 아무것도 발행하지 않는다. 템플릿(볼타 발행 내용에서 작성일자만 뺀 것)·작성일 규칙·계약 기간·mode(기본 test)·approval(기본 manual)·매출계정(기본 4101)·시작 달(선택)을 받아 첫 회차를 미리보기로 점검하고, 회차 목록·회차가 없는 계약 월 경고·승인 토큰을 돌려준다. 같은 공급받는자에 기간이 겹치는 스케줄이 있으면 거부(별개 용역이면 distinct_from_schedule_ids 로 선언). 다른 스케줄이 같은 달을 이미 발행했거나 발행 중이면 거부(거부 메시지에 그 회차 표시). 선발행을 켠 채 승인하면 ‘작성일 전에 발행되면 작성일자 = 발행일’ 까지 승인한 것이다
approve_invoice_schedulewrite승인 토큰으로 초안을 활성화하고 기간 안의 회차를 만든다. 토큰은 스케줄 내용(선발행 여부 포함)에 묶여 있어 내용이 바뀌면 거부되고, 활성화 뒤에 내용이 바뀐 스케줄은 실행되지 않는다. 그 사이 다른 스케줄이 같은 달을 발행했거나 발행 중이면 거부. 라이브 스케줄은 승인 후 자동 발행되며 되돌릴 수 없다
list_invoice_schedulesread스케줄 목록 — 상태, 계약 만료까지 남은 날, 만료 임박 여부, 다음 회차, 발행이 밀린 회차 여부
get_invoice_scheduleread스케줄 1건과 회차 전체(작성일자·실제 보낸 작성일자·상태·금액·승인번호·장부 연결)
update_invoice_occurrencewrite회차 1건 조정 — skip(발행 안 함, 사유 필수) · retry(실패·확인 필요 회차 재시도) · adjust(그 회차만 금액·작성일 조정, 미리보기 토큰 필요) · approve(approval='manual' 스케줄의 회차, 그리고 재개로 보류된 회차의 승인 — 미리보기 토큰 필요). 볼타에 이미 접수된 회차는 건너뛸 수 없다. 다른 스케줄 회차와 같은 달이라 멈춘 회차는 그 회차가 발행 확정된 뒤에만 재시도할 수 있다
set_invoice_schedule_statuswrite일시정지 / 재개 / 종료. 재개하면 정지 중 발행 시점이 지난 회차는 승인 대기로 돌린다(공급했으면 승인, 아니면 건너뛰기). 발행 시점이 재개 뒤인 회차는 정지가 그 달 일부에 걸쳤어도 그대로 자동 발행되니 필요하면 발행 전에 조정한다. 종료(사유 필수, 되돌릴 수 없음)하면 아직 보내지 않은 회차를 모두 취소하고, 이미 발행한 이번 달 이후 회차는 수정발행 검토 미결로 남긴다
renew_invoice_schedulewrite새 계약 기간(선택: 새 템플릿·계약서)으로 후속 스케줄 초안을 만든다 — 승인해야 이어진다. 거래처·mode·approval·매출계정·작성일 규칙·선발행 여부·별개 용역 선언은 이어받는다(그 밖을 바꾸려면 새로 만든다). 이전 스케줄이 아직 잡고 있는 작성월과 겹치거나 이미 후속 스케줄이 있으면 거부
run_invoice_scheduleswrite실행기를 한 번 돌린다(워커와 같은 로직). dry_run 기본 true — 보고만. false 면 만료 처리·결과 재확인·발행·알림

기재 — 고정자산·급여·정기분개

도구스코프설명
register_fixed_assetwrite고정자산 등록
post_depreciationwrite감가상각 분개
dispose_fixed_assetwrite고정자산 처분
match_pending_to_raw_txwrite대기 급여 1건을 원천 거래와 매칭하고 분개 자동 생성. 급여명세서에 기타정산(지급·회수) 항목이 있으면 급여와 나눠 지급은 차변 미지급금, 회수는 대변 가지급금으로 잡고 적요를 분개 라인에 남긴다 — 그 이름의 계정이 계정표에 없으면 분개하지 않고 대기에 남긴다
match_pending_sweepwrite미분류 대기 급여를 일괄 매칭. 같은 직원·기간·금액의 기존 분개가 이미 있으면 자동 매칭 대신 대기 상태를 유지하고 사람 검토를 기다린다
cancel_pending_payrollwrite대기 급여 취소 (송금 취소·퇴사 정산 보류)
sweep_stale_pendingwrite기한이 지난 대기 건을 stale 로 표시
compose_kb_mmf_q_journalswrite분기 MMF 자동 분개 초안
compose_kbsc_q_journalswrite분기 증권계좌 자동 분개 초안
compose_bank_q_journalswrite분기 은행 이자 자동 분개 초안

기재 — 거래처·계좌

도구스코프설명
register_counterpartywrite거래처 등록 (멱등 — 같은 키에 다른 인자면 오류)
list_counterpartiesread거래처 검색 — 이름·사업자번호·법인등록번호·별칭, 특수관계자 필터
update_counterpartywrite거래처 필드 수정 (별칭은 replace/add/remove 중 하나만)
merge_counterpartyclose중복 거래처 병합 — 참조를 전부 옮기고 원본 삭제
suggest_counterparty_tagsread거래처가 비어 있는 분개 라인의 백필 후보를 제안 (읽기 전용 dry-run). 모호하면 제안하지 않는다
apply_counterparty_tagswrite승인된 제안만 커밋. 이미 태깅된 라인은 건너뛰고 덮어쓰지 않는다
list_bank_accountsread은행·카드 계좌 목록
update_bank_accountwrite계좌 메타(별칭·연결 거래처) 수정. 금융 데이터 자체는 불변
reassign_bank_accountwrite원천 거래의 계좌 배정 교정. 금액·일시는 불변
backfill_raw_transaction_amountwrite파서 오류로 0 으로 적재된 금액 1회 복구. 이미 값이 있거나 연결된 분개와 어긋나면 거부

결산

도구스코프설명
closing_previewclose마감 미리보기
closing_commitclose마감 확정
post_quarterly_close_batchclose분기 자동 분개 초안을 한 트랜잭션으로 기재
opening_from_closingclose전기 마감 잔액을 당기 기초로 이월
open_periodclose회계기간 개시
close_periodclose기간 상태 전이 (open → soft_closed → hard_closed, 재개방 포함)

폐지 계정 잔액은 결산 전에 재분류한다 — 마감·이월 분개에는 폐지 계정 전기 예외가 없다. 폐지(기재불가) 표시는 신규 전기를 막으려는 것이라, 잔액을 0 으로 만드는 마감 라인이나 새 기로 넘기는 이월 라인도 예외로 두지 않는다. 대신 막히는 이유를 미리보기에서 지목한다. closing_preview 는 잔액이 남은 폐지 손익계정이 있으면 ACCOUNT_NOT_POSTABLE 로 거부하고, 메시지(폐지 계정 <코드> <계정명> 잔액 <금액> — 재분류 후 마감)와 context.retired_balances 에 해당 계정을 모두 열거한다. closing_commit 은 전기 전에 같은 미리보기를 다시 돌리므로 같은 이유로 거부하고 아무것도 전기하지 않는다. 재무상태표 계정은 마감 분개가 닿지 않으므로 마감을 막지 않는다. opening_from_closing 은 이월 분개가 계정을 찾을 날짜(새 기간 시작일)를 지배하는 정책 era 로 폐지 여부를 판정해, 잔액이 남은 폐지 재무상태표 계정이 있으면 미리보기(dry-run)는 정상 미리보기에 blocked: true 와 blocked_reason(같은 메시지·잔액표·조치)을 얹어 보고하고, force_post 는 같은 메시지로 거부하며 아무것도 전기하지 않는다 — 전기 단계의 일반 거부나 분개 불평형으로 원인이 가려지지 않는다. 조치는 하나다: 각 폐지 계정의 잔액을 사용 중인 통합 계정으로 옮기는 재분류 분개를 먼저 게시하고 다시 마감·이월한다. 재분류 분개의 폐지 계정 쪽 라인은 update_account(is_postable=true) 로 잠깐 되살려 게시한 뒤 곧바로 다시 폐지한다(감사 로그에 남는다).

전기는 법인 단위로 직렬화된다 (아래 셋, frame 다음 ship · 2026-09). 원장에 전표를 세우는 트랜잭션은 — MCP 쓰기 경로만이 아니라 고정자산·세금계산서·펀드·스냅샷·적재 분류처럼 원장에 직접 쓰는 경로까지 — 전부 그 법인의 전기 잠금을 첫 문장으로 잡고 커밋까지 쥔다. 그래서 원장을 다시 읽어 내린 판정이 판정과 기재 사이에 무효가 되지 않는다. 마감 확정이 그 잠금 안으로 들어온 것이 이 축의 본론이다: closing_commit 은 잠금을 잡은 뒤 같은 트랜잭션 안에서 기간을 확인하고, 마감 라인을 다시 계산하고, 순이익을 대조하고, 전기하고, 기간을 소프트클로즈한다. 재계산이 트랜잭션 밖이던 동안에는 그 사이 커밋된 손익 전표 하나가 낡은 라인으로 마감되고 그 잔액이 마감되지 않은 채 닫힌 기간에 남았다 — 되돌리려면 전기된 마감을 역분개하고 기간을 다시 열어야 한다. 미리보기 뒤에 손익 전표가 커밋됐으면 마감은 조용히 새 잔액까지 닫지 않고 순이익 불일치로 거부한다. 전기되는 것은 호출자가 되돌려준 preview_spec 이 아니라 서버가 잠금 안에서 다시 계산한 그 분개이고, 넘어온 preview_spec 의 라인이 그것과 다르면 MATERIALITY_VIOLATION 으로 거부한다 — 미리보기는 제안이고 잠금 안 재계산이 정본이라, 한 분개를 승인했는데 성공 코드와 함께 다른 분개가 전기되는 쪽이 거부보다 나쁘다. 비교는 금액을 정규화하고 라인을 정렬해서 보므로, 미리보기를 JSON 으로 왕복시키거나 순서를 바꿔 넘겨도 걸리지 않는다.

마감된 기간의 판정은 잠금 안에서 한 번, 원장 옆에서 또 한 번. 사전 게이트는 잠금을 잡기 전에 나온 통과권이라, 그것을 쥐고 잠금 앞에 선 평범한 전표는 앞선 마감이 그 사이 기간을 닫고 커밋해도 자기 통과권만 보고 기재한다. 그래서 잠금 안 기간 재확인을 posted 로 서는 모든 전표로 넓혔다 — 예전에는 마감 전표에만, 그것도 호출자가 채워 넣는 문자열을 기준으로 걸려 있었다. 그리고 같은 판정을 DB 트리거가 원장 옆에서 한 번 더 한다: journal 에 posted 행이 들어오거나 다른 상태이던 행이 posted 로 바뀔 때 entry_date 를 덮는 기간이 hard_closed 면 언제나, soft_closed 면 트랜잭션 로컬 설정 frame.allow_soft_closed 가 켜져 있지 않으면 거부다 — 닫힌 기간에 draft 로 넣어 두고 나중에 posted 로 뒤집는 우회도 같은 판정을 받는다. 판정의 근거인 기간 행은 그 쓰기가 커밋할 때까지 붙들려 있어, 판정과 기간 마감이 엇갈리지 않는다. 게이트를 호출 지점마다 복제하면 새 경로가 하나 생길 때 조용히 빠지므로(실제로 그렇게 빠져 있었다) 판정을 원장 옆에 못박았다 — 파이썬 층을 지나지 않는 직접 기재도, 다른 언어로 쓰인 자동분개도 같은 답을 받는다. 그 설정은 post_journal·reverse_journal 이 받는 명시적 인자 allow_soft_closed 가 켠다 — 이미 소프트클로즈된 기간에 전표를 세워야 하는 두 쓰기 도구다. 마감 자체는 그 인자를 쓰지 않는다: closing_commit 은 아직 열린 기간에 전기하고, 소프트클로즈는 같은 트랜잭션에서 그 뒤에 한다. 설정은 트랜잭션 로컬이라 커밋·롤백에서 저절로 풀린다. entry_date 를 덮는 기간이 아예 없으면 통과시킨다 — 첫 회계기간 이전의 과거 이관이 그 자리다.

닫힌 기간에서는 역분개 계보도 같은 문을 지난다. 수동으로 만든 반대 분개를 원본과 사후 연결하는 relink_reversal 과 링크만 채우는 백필은 원본의 상태와 역분개 링크를 고치므로, 원본의 기간이 닫혀 있으면 거부된다 — 두 함수 다 allow_soft_closed 를 켜지 않으므로 소프트클로즈도 예외가 아니고, 소프트클로즈든 하드클로즈든 close_period 재개방 전이(close 스코프)로 기간을 먼저 열어야 한다. 숫자는 한 푼도 움직이지 않지만 list_journals(status='reversed') 와 총계정원장의 역분개 숨김, 역분개 쌍 무결성 검사가 정확히 그 두 열을 읽는다 — 닫힌 해의 그림이 재개방 흔적 없이 바뀌는 것을 막는 것이 이 판정이다. 링크만 채우는 백필은 예전에 이 판정에서 면제돼 닫힌 해에도 돌았고, 그 면제는 날 SQL 이 하드클로즈된 해의 계보를 아무 잠금 없이 옮기는 길이기도 해서 함께 없어졌다.

역분개 계보는 원장이 직접 지킨다. reversed 로 표시된 전표는 자기를 되감은 상대 전표를 반드시 가리켜야 하고, 링크 없는 reversed·자기 자신을 가리키는 링크·존재하지 않는 전표를 가리키는 링크는 어떤 쓰기 경로로도 원장에 들어가지 못한다. 링크된 상대 전표만 따로 지울 수도 없다. 예전에는 이 규칙을 쓰기 도구만 지켜서, 도구를 우회한 쓰기가 깨진 계보를 남겼고 정합성 검사가 사후에 찾아야 했다. 규칙 도입 이전에 남은 손상 행은 고치지 않고 그대로 둔다 — 새로 들어오거나 바뀌는 행에만 적용되고, 정합성 검사가 그 행들을 계속 보고한다.

이월의 폐지 판정은 도착 기간의 정책 era 에서 읽는다. 한 계정코드가 여러 회계정책 era 에 걸치면 era 마다 계정 행이 따로 있고 계정 수정은 한 era 만 바꾼다. 잔액을 era 행 단위로 묶던 동안에는 두 방향으로 어긋났다 — 옛 era 는 살아있고 도착 era 가 폐지면 게이트가 아무것도 못 본 채 이월이 전기에서 깨졌고, 반대면 이미 지나간 era 의 폐지 표시가 멀쩡한 이월을 막아 지나간 era 의 계정을 되살려야 풀렸다. 이제 잔액은 계정코드로 합치고 폐지 여부·계정명·유형은 새 기간 시작일을 지배하는 era — 이월 분개가 실제로 계정을 찾을 그 행 — 에서 읽는다(지배 era 판정은 전기와 같은 규칙이다). 도착 era 에 그 코드가 아예 없으면 전기 불가로 보고, 도중에 깨지느니 무엇을 재분류해야 하는지 알려 주며 막는다.

관리

도구스코프설명
register_entityadmin법인·펀드 등록 + 표준 계정과목 자동 시딩. 사업자등록번호·법인등록번호(체크디짓 검증). 다른 등록·배포 마이그레이션이 진행 중이면 최대 10초 기다리며, 그 안에 등록을 시작하지 못하면 ENTITY_PROVISIONING_BUSY를 반환한다. 이 오류에서는 아무것도 기록하지 않으며, 진행 중인 작업이 끝난 뒤 같은 인자로 재시도한다.
update_periodadmin열려 있는 기간의 시작·종료·라벨·비고 수정
list_accountsread계정과목 조회 — 유형·상위계정·기재가능 여부 필터
create_accountadmin계정과목 신설 — 유형 검증 + 상위계정 존재 검증
update_accountadmin계정과목 이름·상위계정·활성여부·순서 수정 (코드·유형은 불변)
delete_accountadmin계정과목 삭제. 분개에서 쓰이거나 자식 계정이 있으면 거부
list_accounting_policiesread적용 중인 회계기준 정책 조회
create_accounting_policyadmin새 회계기준 정책 생성 (기준 개정 등)
update_accounting_policyadmin정책의 기준·적용시작·적용종료·비고 수정
list_scrape_schedulesread포털 수집 주기 목록
get_scrape_scheduleread단건 수집 주기 (지연 여부 포함)
set_scrape_schedulewrite수집 주기 설정 (cron 또는 daily/weekly/monthly 프리셋, KST)

공개 API — 스키마 목록

Frame 이 생산하는 사실(fact)의 타입 규격을 그대로 노출한다. 다른 서비스나 에이전트가 이 규격을 가져다 캐시·검증에 쓴다.

curl -H "Authorization: Bearer $TOKEN" \ https://frame.axelabs.ai/frame/schemas

응답 봉투는 안정 형식이다.

{ "version": "1.0", "service": "frame", "schemas": { "[email protected]": { "description": "단일 계정의 시점 잔액 (차변/대변 합계 + 순 잔액).", "produced_by": ["query_balance"], "key_fields": ["entity_id", "account_code", "as_of_date", "debit", "credit", "balance", "policy_id"] } } }

현재 13종을 노출한다 — 잔액 · 시산표 · 분개 · 분개목록 · 원천거래 · 미결 · 결의서 · 고정자산 장부가액 · 손익계산서 · 재무상태표 · 현금흐름표 · 자본변동표 · 총계정원장.

  • 인증 필요 — MCP 클라이언트와 동일한 토큰을 그대로 쓴다.
  • 버전 — 스키마 ID 의 @1.0 접미사가 개별 스키마의 호환성을, 봉투의 version 이 응답 모양 자체의 변경을 나타낸다.

시작하기

  1. 법인 등록 — 등록 시점에 KSME 표준 계정과목이 자동으로 복사된다. 별도 시딩 작업이 없다.
  2. 원천 데이터 적재 — 은행·카드 거래내역 파일을 올린다. 포맷은 자동 인식된다. 처음 보는 포맷이면 몇 가지를 되묻고, 그 답을 캐시해 다음부터는 묻지 않는다.
  3. 기초 잔액 등록 — 외부 회계법인 검수본 기준 시산표를 개시 분개로 기재한다.
  4. 분개 — 자동 매칭이 붙는 건은 제안을 확인하고 커밋하고, 나머지는 직접 기재한다. 진척은 시산표로 매일 확인한다.
  5. 마감 — 기간을 가마감 → 확정으로 전이시키고, 다음 기 기초로 이월한다.

관련 문서