{ "schema_version": 1, "diagram_type": "dataflow", "meta": { "title": "증거 데이터 흐름 — 수집에서 판정까지", "output": "docs/diagrams/evidence-dataflow.html", "quality_profile": "showcase", "views": [ { "id": "collect-boundary", "label": "수집 경계", "focus": [ "vision", "cse", "naver", "policy", "normalizer" ], "note": "외부 응답이 Evidence 가 되기까지 통과하는 데이터 등급 경계." }, { "id": "scoring", "label": "채점", "focus": [ "normalizer", "scorer", "knowledge" ], "note": "제공자별 풀·버킷과, 풀링 대상이 아닌 지식DB 승격 경로." }, { "id": "roundtrip", "label": "라운드트립", "focus": [ "payload", "sqlite", "restore", "scorer" ], "note": "저장과 복원이 원 점수를 재현해야 하는 고리." } ], "viewBox": [ 1080, 500 ], "legend": { "mode": "auto", "entries": { "emphasis": { "label": "주 경로" }, "security": { "label": "등급 통제" }, "database": { "label": "저장소" }, "default": { "label": "데이터 흐름" } } } }, "stages": [ { "label": "수집" }, { "label": "경계 검사" }, { "label": "정규화 · 채점" }, { "label": "영속화" }, { "label": "소비" } ], "nodes": [ { "id": "vision", "type": "external", "label": "Cloud Vision", "sublabel": "웹 탐지 · 엔티티", "tag": "match", "brand": "google-cloud", "stage": 0, "row": 0 }, { "id": "cse", "type": "external", "label": "Google 맞춤 검색", "sublabel": "이미지 · 웹문서", "tag": "match=page", "stage": 0, "row": 1 }, { "id": "naver", "type": "external", "label": "네이버 검색", "sublabel": "블로그 · 웹문서", "tag": "promoted", "stage": 0, "row": 2 }, { "id": "knowledge", "type": "database", "label": "지식DB · 신뢰 출처", "sublabel": "지문 · 자사 도메인", "tag": "내부", "stage": 2, "row": 2 }, { "id": "policy", "type": "security", "label": "데이터 등급 검사", "sublabel": "payload 허용 목록", "tag": "SEARCH_EVIDENCE", "stage": 1, "row": 1 }, { "id": "normalizer", "type": "backend", "label": "증거 정규화", "sublabel": "Evidence 레코드", "tag": "source", "stage": 2, "row": 0 }, { "id": "scorer", "type": "backend", "label": "RiskScorer", "sublabel": "한 풀 · 제공자별 버킷", "tag": "v7", "stage": 2, "row": 1 }, { "id": "payload", "type": "backend", "label": "_evidence_payload", "sublabel": "도메인 → payload", "tag": "host 해석", "stage": 3, "row": 0 }, { "id": "sqlite", "type": "database", "label": "evidence 테이블", "sublabel": "payload JSON · WAL", "tag": "cascade", "stage": 3, "row": 1 }, { "id": "restore", "type": "backend", "label": "증거 복원", "sublabel": "payload → 도메인", "tag": "복원", "stage": 3, "row": 2 }, { "id": "console", "type": "frontend", "label": "운영자 콘솔", "sublabel": "증거 카드 · host 칩", "tag": "판정", "stage": 4, "row": 0 }, { "id": "llm", "type": "backend", "label": "LLM 증거 판독", "sublabel": "상위 12행 화이트리스트", "tag": "ko-v4", "stage": 4, "row": 1 } ], "flows": [ { "id": "vision-payload", "from": "vision", "to": "policy", "label": "웹 탐지 결과", "classification": "외부 응답", "route": "top-channel" }, { "id": "cse-payload", "from": "cse", "to": "policy", "label": "검색 결과", "classification": "외부 응답", "route": "straight" }, { "id": "naver-payload", "from": "naver", "to": "policy", "label": "블로그 · 웹문서", "classification": "외부 응답", "route": "bottom-channel" }, { "id": "allowed-fields", "from": "policy", "to": "normalizer", "label": "허용 필드만 통과", "classification": "등급 통제", "variant": "security" }, { "id": "evidence-record", "from": "normalizer", "to": "scorer", "label": "채점 입력 신호", "classification": "주 경로", "variant": "emphasis", "labelDy": 36 }, { "id": "fingerprint-match", "from": "knowledge", "to": "scorer", "label": "지문 유사도 0.9+ → 80점", "classification": "풀링 제외", "labelDy": -20 }, { "id": "score-band", "from": "scorer", "to": "payload", "label": "점수 · 밴드 · 사유", "classification": "주 경로", "variant": "emphasis" }, { "id": "serialize", "from": "payload", "to": "sqlite", "label": "payload JSON · host", "classification": "주 경로", "variant": "emphasis", "labelDy": 36 }, { "id": "reload-restore", "from": "sqlite", "to": "restore", "label": "리로드 · 판정 시 복원", "classification": "읽기 경로", "labelDy": 36 }, { "id": "roundtrip-invariant", "from": "restore", "to": "scorer", "label": "원 점수 재현", "classification": "불변식", "variant": "emphasis" }, { "id": "bootstrap-read", "from": "sqlite", "to": "console", "label": "bootstrap 조회", "classification": "읽기 경로" }, { "id": "evidence-reading", "from": "restore", "to": "llm", "label": "증거 판독 요청", "classification": "읽기 경로" } ], "cards": [ { "dot": "emerald", "title": "주 경로", "items": [ "외부 응답은 데이터 등급 검사를 통과한 필드만 Evidence 가 된다", "RiskScorer v7 는 웹 존재를 제공자 무관 한 풀로 센다 (presence 40 / entity 10)", "점수 · 밴드 · 사유는 payload 로 직렬화되어 evidence 테이블에 남는다", "신뢰 출처(자사·계약처 도메인)에서 발견된 행은 0점이다 — 행 단위 제외라 스크래퍼 게시는 그대로 센다" ] }, { "dot": "rose", "title": "라운드트립 불변식", "items": [ "_evidence_payload 로 직렬화하고 _domain_evidence_from_ui 로 복원한다", "복원된 증거를 다시 채점하면 원 점수가 재현되어야 한다", "result_url → url 별칭이 0점을 45점으로 바꾼 사고가 있었다", "host 는 저장 시 해석하고 복원 시 우선 반환한다 — API 이름으로 되돌아가지 않는다" ] }, { "dot": "orange", "title": "소비 경로", "items": [ "콘솔은 영속화된 payload 를 읽는다 — 호스트 칩은 20ch 로 잘리고 전체는 툴팁에 있다", "LLM 은 복원된 증거 상위 12행만 본다 — 인용 없는 claim 은 폐기된다", "지식DB 지문 매칭은 풀링 대상이 아니며, 라벨만으로는 닿지 않는 high 승격 경로다" ] } ] }