외부 공식 API 호출
run-due 727 sources879 fetch_observations
Regulatory Ingestion · Gate F
법령 원문을 외부 공식 API에서 수집해 조문 단위로 쪼개고, 카드사 의무 후보로 분류한 뒤 사람이 검토·승인하는 append-only 파이프라인. 모든 판단 근거와 원문이 원장에 남습니다.
쏟아져 들어오는 법령을 낱장으로 정리해, "우리 카드사가 확인할 의무"만 근거와 함께 검토대에 올리는 선별 공장입니다. 기계는 1차 후보를 추리고 관련 조문을 붙이는 데까지 맡고, 승인 도장은 법무·컴플라이언스 담당자만 찍습니다.
증거를 다루는 방식은 두 가지 원칙으로 고정됩니다. 원문은 절대 고쳐 쓰지 않고, 요약 대신 법 문장 그대로를 보여줍니다. 또 과거 판단을 지우거나 덮어쓰지 않고, 누가 언제 어떤 근거로 판단했는지 새 줄로 계속 남깁니다. 감사·검사 때 "왜 이렇게 판단했나"를 원문까지 거슬러 올라가 설명하기 위한 장부입니다.
각 단계는 독립 CLI 명령이고, 결과를 원장에 쓴 뒤 다음 단계가 그것을 읽습니다. 중간 산출물이 전부 테이블로 남아 어느 단계든 단독 재실행·검증이 가능합니다.
공정마다 결과물을 장부에 내려놓고 다음 공정이 가져가는 구조입니다. 그래서 4단계 기준표를 고쳐도 1~3단계를 되풀이할 필요 없이, 4단계만 다시 돌려 결과를 비교할 수 있습니다.
project-relations → 10,377 fragment_relations
match-activities → 1,475 activity_obligation_matches
project-source-changes → 771 source_changes
naver-news → 240 NEWS fragments
위의 메인 공정이 원문을 의무 후보로 바꾸는 컨베이어 벨트라면, 이 넷은 그 옆의 보조 작업대입니다. 조문 간 관계는 법전의 각주와 화살표를 이어 붙이고, 업무 매칭은 의무 카드를 담당 부서의 서류함에 나눠 넣습니다. 개정 감지는 예전 승인에 "다시 확인" 표지를 붙이고, 뉴스 모니터링은 관련 보도를 스크랩해 둡니다. 뉴스와 의무의 최종 연결은 사람이 확인합니다.
의존 방향은 항상 안쪽으로만 흐릅니다. 왼쪽 색띠는 장식이 아니라 신뢰 경계입니다 — 외부에서 들어온 미검증 데이터가 어디서 정규화되고, 어디서부터 원장에 고정되는지를 나타냅니다.
공식 API·HTML만 호출합니다. 호스트 화이트리스트, 429·5xx 재시도, 이용약관 검토 상태를 통과하지 못하면 수집 자체가 차단됩니다(fail-closed).
밖에 나가서 물건을 받아오는 구매 담당. 거래처가 승인 목록에 없으면 아예 안 나갑니다.
law-open-apilaw-open-api-preclaw-open-api-ppclaw-open-api-fscnaver-newspipc-press-releasesfsc-press-releasesllm-classifier-anthropicsecure-httpfactory
파싱과 판정 규칙만 있습니다. DB도 네트워크도 모릅니다. 의무 분류 규칙
(obligation-rules)이 여기 있고, 어미·수범자 패턴이 전부 명시 상수라
판정 근거를 조문 단위로 되짚을 수 있습니다.
벽에 붙은 판정 기준표 그 자체. 아무 일도 하지 않고, 기준만 적혀 있습니다.
obligation-rulessource-fragmentslaw-documentadmrul-documentprecedent-documentppc-decision-documentfsc-decision-documentnaver-news-articlefragment-relationsendpoint-definitionintegritycanonical-jsonnormalized-diff
파이프라인 각 단계가 한 파일씩 대응됩니다. 커넥터·도메인·원장을 조립만 하고 비즈니스 규칙은 갖지 않습니다. 사람 판단이 필요한 동작(검토·중복지정·뉴스연결·재검토 해소)은 모두 여기서 명시적 액션으로만 실행됩니다.
현장 반장의 작업 지시서. "누가 무엇을 어떤 순서로"만 정하고, 판정 기준은 바꾸지 않습니다.
collect-sourcecollect-batchproject-fragmentsproject-obligationsproject-relationsreview-obligation-candidategenerate-llm-classificationsapply-llm-classificationsmatch-activity-obligationsexport-obligation-reviewsdraft-guideline-documentacknowledge-stale-obligationlink-news-to-obligationrun-due-endpointsverify-runtime
SQLite 원장 하나(node:sqlite 내장, 외부 DB 없음)와 콘텐츠 주소 저장소.
원본 바이트는 sha256으로 주소화해 불변 보존하고, 검토 이력은 수정 없이 누적만 됩니다.
스키마 v28까지 마이그레이션이 전부 코드에 남아 과거 백업도 현재 스키마로 복원됩니다.
봉인 금고 + 손으로 쓴 장부. 새 줄만 추가되고, 이미 쓴 줄은 고치거나 지울 수 없습니다.
sqlite-ledgercontent-addressed-storejsonl-event-sink
루프백 전용 웹 콘솔 9화면과 건강도·백업·소크 판정. 쓰기 경로는 딱 4개 (의무 검토, 수범자 승인, 뉴스 연결, 재검토 해소)로 제한되고 나머지는 전부 읽기 전용입니다. DNS 리바인딩 방어를 위해 Host 헤더까지 검사합니다.
사람이 실제로 보는 창구 화면. 볼 수 있는 건 많지만, 손댈 수 있는 건 4가지뿐입니다.
console-serverconsole-assetsoperations-snapshotpipeline-healthruntime-backupsoak-readiness
이 다섯 계층은 바깥에서 들어온 정보를 믿을 수 있는 기록으로 바꾸는 순서입니다. 커넥터가 외부 자료를 받아오면 도메인이 순수 규칙으로 뜻을 판정하고, 애플리케이션이 처리 순서를 조율합니다. 인프라는 결과를 원장에 영구 보존하며, 운영·콘솔은 사람이 마지막으로 확인하고 다루는 창구가 됩니다.
실제 운영 런타임 .runtime/gate-f-2026-08-04 기준 행수. 38개 테이블 중 데이터가 있는 21개입니다.
별도 데이터베이스 서버 대신 약 390MB짜리 파일 하나가 전체 장부입니다. 장부 파일을 통째로 복사하면 그 시점의 백업이 되고, 다른 PC로 옮겨도 같은 기록을 열 수 있습니다.
아래 표의 행은 장부에 쌓인 기록 수입니다. 가장 중요한 대비는 의무 후보 10,408건 vs 사람 검토 2건입니다. 자동 선별 결과는 충분히 쌓였지만, 이를 최종 확정하는 사람의 검토는 거의 시작되지 않았다는 뜻입니다.
| 테이블 | 역할 | 행 |
|---|---|---|
| 수집 · 증거 보존 | ||
sources | 수집 대상 문서 식별 | 727 |
source_versions | 불변 스냅샷 (재수집마다 새 버전) | 771 |
artifacts | 원본 바이트 sha256 주소화 | 1,542 |
collection_runs | 수집 실행 이력 | 96 |
collection_items | 배치 내 개별 항목 | 879 |
fetch_observations | HTTP 응답 관측 기록 | 879 |
source_availability_observations | 가용성 상태 전이 | 879 |
source_changes | 버전 간 실질 변경 분류 | 771 |
| 분해 · 판정 | ||
source_fragments | 조·항·호 단위 원문 조각 | 11,150 |
obligation_candidates | 의무 후보 + 판정 근거 | 10,408 |
fragment_relations | 위임·인용·제재 엣지 | 10,377 |
obligation_candidate_reviews | 사람의 최종 결정 (append-only) | 2 |
| 업무 연결 | ||
business_activities | 처리활동 인벤토리 (현재 가상 데이터) | 21 |
activity_obligation_matches | 업무 × 의무 매칭 + 근거 | 1,475 |
regulated_subjects | 승인된 수범자 패턴 | 24 |
| 거버넌스 · 운영 | ||
source_endpoint_versions | 승인된 엔드포인트 정의 | 51 |
endpoint_governance_states | 중단·재개·검토기한 게이트 | 50 |
endpoint_governance_actions | 거버넌스 조치 이력 | 50 |
scheduled_endpoints | 수집 스케줄 · 리스 | 50 |
outbox_events | 외부 발행 대기 이벤트 | 814 |
operational_events | 운영 조치 감사 로그 | 88 |
수집·분류는 사실상 완료됐고, 병목은 전부 사람 검토 단계에 몰려 있습니다.
미검토 DUTY 1,094건 + DISCRETION 962건 = 2,056건. 건당 3분이어도 103시간, 법률 해석이 필요한 건은 10분이 넘습니다. 큐 UI를 아무리 빠르게 만들어도 2,056 → 0은 달성 불가능한 목표입니다.
그래서 재구성 방향은 셋입니다 — ① DISCRETION 962건은 "할 수 있다"이지 의무가 아니므로 검토 대상에서 제외, ② 제재조항이 연결된 DUTY 204건만 전수 검토 트랙으로 분리(감사 대응 논리가 가장 명확), ③ 나머지는 조문 단위가 아니라 이미 구축된 업무 21개 · 매칭 1,475건을 축으로 부서가 나눠 확인. 실제 사람 부담이 2,056건 → 204건 전수 + 업무 21개로 떨어집니다.
위 막대는 앞의 자동 공정은 끝났지만 마지막 사람 검토 줄만 거의 비어 있음을 보여줍니다. 서류 분류와 참고 표시까지는 끝났는데, 최종 결재함에 문서가 쌓여 있는 상태입니다.
남은 2,056건을 한 명이 처음부터 끝까지 모두 보는 방식은 현실적으로 지속할 수 없습니다. 그래서 목표를 "전부 검토한다"에서 "중요한 것을 빠뜨리지 않았다고 증명할 수 있다"로 바꿉니다.
DISCRETION은 "~할 수 있다"는 선택 규정이므로 이 계획의 전수 검토 줄에서는 분리합니다. 제재조항이 걸린 204건은 어기면 과태료·형벌로 이어질 수 있어 전부 확인하고, 감사에도 "제재가 연결된 건은 모두 봤다"고 설명할 수 있게 합니다. 나머지는 법전 순서대로 넘기는 대신 "카드발급 업무에 걸린 의무 15건"처럼 업무별 묶음으로 보내 담당 부서가 자기 업무 기준으로 확인합니다. 실제 현업의 책임 단위와 같은 방식입니다.