본문으로 건너뛰기

intel_bronze_sink 노드 QA 가이드 — Bronze 적재 + MCP 자동 등록

이 문서는 Pipeline Studio의 intel_bronze_sink 노드(Intel 셀프서비스 수집 Slice C, #2289)를 QA가 화면에서 단계별로 검증할 수 있도록 실제 prod(gend.genon.ai)의 finance-invest 워크스페이스 화면과 함께 정리한 것입니다.

개요

intel_bronze_sink는 upstream(예: rest_source)의 records[]를 받아 "PS에서 만들면 즉시 조회 가능한 MCP 인텔 도구" 루프를 닫는 종단(sink) 노드입니다:

  1. Bronze 적재 — 공유 테이블 iceberg.bronze.intel_<domain>_raw(workspace_id, content_hash) dedup append (재실행 중복 방지, 불변식 I4).
  2. MCP 자동 등록 — 적재 후 WorkspaceMcpTool을 자동 등록해, 워크스페이스가 MCP tools/list에서 바로 조회 도구로 사용.

★ 워크스페이스 격리 (cross-ws 누출 차단, I5)

bronze는 전 워크스페이스가 공유하는 단일 물리 테이블이고 행은 workspace_id 컬럼으로만 구분됩니다. 따라서 자동 등록되는 MCP 도구는 서버가 강제 주입하는 ws-펜스(query_spec.ws_fenced_col)로만 자기 워크스페이스 행을 조회합니다 — 이 펜스는 호출자가 변경할 수 없고(필터가 아님), 펜스 없는 공유-테이블 도구는 dispatch에서 **거부(fail-closed)**됩니다. 또한 ws-펜스 도구는 마켓플레이스 publish가 금지됩니다(publisher private 행 누출 방지).

신원: 적재 워크스페이스는 run_id → PipelineStudioRun 바인딩에서 서버사이드로 파생되며, 노드 config의 workspace_id는 신뢰하지 않습니다(D10).

현재 상태: 작성·실행 모두 prod 라이브입니다. egress-proxy 는 2026-06-25 전체 활성화됐고 (Epic #2286), rest_source → intel_bronze_sink 풀체인 E2E 가 prod 에서 검증됐습니다 — 본 가이드의 절차만으로 실제 적재·MCP 조회까지 동작합니다.


1. 팔레트에서 intel_bronze_sink 선택

Pipeline Studio에서 새 파이프라인을 만들면 빌더가 열립니다. 좌측 노드 팔레트에 싱크 (Intel Bronze + MCP) 항목이 있습니다.

Pipeline Studio 팔레트의 intel_bronze_sink 노드


2. 캔버스에 드래그&드롭

**싱크 (Intel Bronze + MCP)**를 캔버스로 끌어다 놓으면 intel_bronze_sink 노드가 생성됩니다. (종단 노드 — records를 입력으로 받습니다.)

캔버스에 놓인 intel_bronze_sink 노드


3. config 폼

노드를 클릭하면 우측에 설정 폼이 열립니다.

intel_bronze_sink config 폼 필드

필드설명
source출처 라벨 (예: dart)
domainbronze 테이블 iceberg.bronze.intel_<domain>_raw의 일부 — 안전 식별자만(예: filings)
external_id_pathpayload에서 외부 ID를 뽑을 path (예: $.rcept_no). 미설정 시 content_hash 사용
중복·변경 정책 (write_mode)같은 external_id내용이 달라졌을 때 어떻게 적재할지. 버전 누적(기본) = 새 버전 행 추가(이력 보존), 최신으로 교체 = 새 행 적재 후 구버전 행 제거(external_id 당 최신 1행 수렴, 이력 미보존). 내용이 같으면 어느 모드든 중복 스킵
검색 필드 (search_fields)이름 → payload JSON 경로 맵 (예: law_name$.법령명한글). 자동 등록되는 MCP 도구에 <이름>_like 부분일치 검색 인자(선택 인자)가 추가됩니다. 이름은 snake_case, 경로는 $.필드(.하위) 형식만 허용
MCP 기본 최신행만 (latest_only, 고급)기본 — 버전 누적 테이블에서 external_id최신 1행만 기본 반환하고, 호출 시 all_versions=true 인자로 전체 버전을 조회합니다 (#2529). 이미 등록된 도구는 이 값을 명시적으로 바꿔 저장했을 때만 변경됩니다 — 설정을 건드리지 않으면 기존 도구의 조회 의미(publish/구독 포함)가 정기 실행만으로 바뀌지 않습니다
검색 인덱싱 (search_index_*, 그룹)켬(opt-in) 시 적재 레코드를 청킹→임베딩→Weaviate 인덱싱하고 search_<domain> MCP 검색 도구(시맨틱/하이브리드/키워드)를 자동 등록합니다 (#2594). search_text_paths(payload JSON 경로 목록, 필수)·청크 크기/오버랩·임베딩 프로바이더(선택). 인덱싱 실패는 실행을 죽이지 않고 실행 요약에 오류로 표기(fail-soft — bronze 원장은 이미 커밋)
MCP 도구적재 후 자동 등록될 워크스페이스 MCP 조회 도구. tool_name + description 분리 입력(#2323 — raw JSON 직접 입력 아님; 두 칸을 채우면 {tool_name, description}으로 자동 조립). ws-펜스는 서버가 강제
silver 매핑 (JSON, 선택)silver canonical 매핑(선택)

4. config 입력 예시

source/domain을 채우고, MCP 도구tool_name(예: query_intel_my) + description 두 칸에 입력합니다.

source/domain 입력 + MCP 도구 2칸

MCP 도구 입력(#2323): 과거엔 {"tool_name":...,"description":...} raw JSON을 직접 입력했으나, 이제 tool_name / description 분리 텍스트 입력입니다. 따옴표·중괄호 실수 없이 두 칸만 채우면 서버 계약({tool_name, description})으로 자동 조립됩니다.

MCP 도구 2칸 분리 입력

중복·변경 정책 + 검색 필드 (PR-1 #2589)최신으로 교체를 선택하고 검색 필드에 law_name$.법령명한글을 입력한 모습:

중복·변경 정책 select + 검색 필드 kv 입력

고급 설정 → MCP 기본 최신행만 (latest_only) — 접이식 고급 섹션을 열면 최신행 노출 설정이 보입니다:

고급 설정의 MCP 기본 최신행만 select

확인 포인트(QA)

  • 적재 후 워크스페이스 MCP tools/listtool_name이 출현하고, 그 도구는 자기 워크스페이스 bronze 행만 반환합니다(cross-ws 누출 없음).
  • domain은 안전 식별자가 아니면 422로 거부됩니다(SQL injection 방지).
  • 같은 (workspace_id, content_hash)는 재적재 시 skip됩니다(중복 방지).
  • 공유 bronze 테이블 대상 MCP 도구를 ws-펜스 없이 만들려 하면 차단됩니다(I5).
  • 검색 필드를 등록했다면 MCP 도구 inputSchema에 <이름>_like 인자가 나타나고, 부분일치 값으로 호출하면 해당 payload 필드 기준으로 필터링됩니다. 도구 설명문에는 실제 대상 테이블 FQN이 표시됩니다(#2544).
  • 최신으로 교체 모드에서 같은 external_id의 내용을 바꿔 재적재하면 실행 요약에 N건 최신으로 교체가 표시되고, 테이블에는 최신 1행만 남습니다.

5. 실행 결과 확인

실행이 끝나면 실행 탭에서 해당 실행을 펼치면 적재 결과 패널에 Bronze N행 적재 · M건 스킵(중복) → <테이블> 요약과 등록된 MCP 도구, 적재 레코드 샘플이 표시됩니다. 최신으로 교체 모드로 기존 행이 대체된 경우 · K건 최신으로 교체가 요약에 덧붙습니다.

적재 결과 패널 — 요약 + MCP 배지 + 샘플 (prod 실측) (재실행으로 전부 중복 스킵된 경우 "신규 없음 — 전부 중복 스킵" 으로 표시됩니다 — 실패가 아닙니다.) SQL 로 직접 확인하려면:

SELECT count(*), max(fetched_at) FROM iceberg.bronze.intel_<domain>_raw;

보안·무결성 요약 (참고)

상황동작
자기 워크스페이스 도구 조회서버 강제 ws-펜스 → 자기 행만
펜스 없는 공유-테이블 도구 dispatch거부(fail-closed)
ws-펜스 도구 마켓플레이스 publish거부(422) — publisher private 누출 방지
동일 (ws, content_hash) 재적재skip(중복 방지, I4)
최신으로 교체 모드 재적재내용이 달라진 external_id의 구버전 행만 교체(무변경 행 무접촉). INSERT 후 DELETE 순서라 부분 실패 시에도 원장(bronze) 유실이 없습니다 — 최악은 구버전 행 잔존(MCP 최신행 윈도우가 가림, 다음 변경 적재 시 수렴). DELETE 도 ws-펜스 내에서만
최신으로 교체 동시 실행같은 external_id 를 동시에 적재하는 두 실행이 겹치면 일시적으로 2행이 남을 수 있으나(유실·덮어쓰기 없음) 최신행 윈도우가 가리고 이후 수렴합니다
search_<domain> 검색 도구Weaviate 공유 컬렉션(intel_<domain>)을 서버 강제 workspace_id 펜스로만 조회(I5) — 검색어는 GraphQL 리터럴로 이스케이프(인젝션 차단), 결과는 HMAC 서명 검증 후 반환. publish 금지(ws-펜스 도구 게이트)
검색 인덱스 버전write_mode 와 무관하게 external_id 당 최신판만 인덱싱(이력 검색은 비목표 — 원장은 bronze). 최신판의 텍스트 경로가 비면 기존 청크도 제거(delete-only — stale 검색 결과 방지)
검색 필드 이름/경로snake_case + $.필드 형식만 허용 — 인용부호·괄호·와일드카드 422(injection 차단), 저장 스펙 위·변조 시 실행 시점에도 fail-closed
malformed sink_configbronze 적재 전 422(부분 적재 없음)

자동 검증

이 가이드의 단계는 ui/tests/intel-bronze-sink-e2e.spec.ts(Playwright)로 자동 검증되며, QA_CAPTURE=1로 실행하면 위 스크린샷이 재생성됩니다.

E2E_BASE_URL=https://gend.genon.ai E2E_USERNAME=... E2E_PASSWORD=... \
QA_CAPTURE=1 pnpm exec playwright test intel-bronze-sink