From 780bbd60db4b996f49b87c27cdec9af60bf9e651 Mon Sep 17 00:00:00 2001 From: devmrko Date: Tue, 30 Jun 2026 14:40:32 +0900 Subject: [PATCH] [Developer] #572 separate vector search and VPD filter trace --- .../README.md | 54 +++++++++++++++++++ .../templates/fragments/probe-result.html | 15 +++++- .../web/GuidedFlowTemplateTest.java | 3 ++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 docs/design/572-vector-vpd-filter-separation/README.md diff --git a/docs/design/572-vector-vpd-filter-separation/README.md b/docs/design/572-vector-vpd-filter-separation/README.md new file mode 100644 index 0000000..289149c --- /dev/null +++ b/docs/design/572-vector-vpd-filter-separation/README.md @@ -0,0 +1,54 @@ +# 설계서: VECTOR_DISTANCE와 역할 기반 VPD 필터 분리 표시 (#572) + +> **상태**: Approved +> **작성**: [AI] Architect · **최종수정**: 2026-06-30 +> **추적성** — Redmine: #572 · 선행 기능: #558, #570, #571 +> · 구현 파일: `probe-result.html`, `OrdsProbeService`, `GuidedFlowTemplateTest` +> · 테스트: `mvn test` + +## 1. 목적 + +벡터 검색의 유사도 계산과 VPD 권한 필터를 서로 다른 개념으로 표시한다. + +- **벡터 검색**: `VECTOR_DISTANCE(d.embedding, TO_VECTOR(:embedding), COSINE)`로 score를 계산하고 `ORDER BY score`로 가까운 순서의 Top-K를 반환한다. +- **권한 필터**: `set_vpd_context`가 설정한 사용자/역할을 `CB_AGENT_DOC_VPD_FILTER`가 읽고, 해당 역할의 permission rule에 따라 `TECH_TAG` 등 대상 컬럼 조건을 만든다. 이 조건은 검색어가 아니라 접근 통제다. + +최종 effective SQL에는 두 조건이 함께 존재할 수 있지만, 화면에서는 각각을 분리해 오해를 막는다. + +## 2. 인수조건 + +- [ ] 벡터 결과에 `VECTOR_DISTANCE`와 `ORDER BY score`가 “벡터 유사도 검색 기준”으로 별도 표시된다. +- [ ] `REGEXP_LIKE`가 있으면 “역할 기반 VPD 권한 필터”로 표시하고, 벡터 검색 조건이 아님을 설명한다. +- [ ] 권한 필터 설명에 선택 사용자에게 직접/그룹으로 연결된 role의 permission rule에서 계산되었다고 표시한다. +- [ ] `ALL` 권한은 `1 = 1`, 권한 없음/허용 rule 없음은 `1 = 0`, TAG 권한은 해당 role의 TAG 값만 표시한다. +- [ ] 최종 effective SQL은 실제 결합 형태를 유지하되, 화면 앞에서 검색 기준과 권한 필터를 분리해 보여준다. +- [ ] 일반 객체의 기존 VPD trace, 사용자 context, SQL 결과는 회귀하지 않는다. + +## 3. 화면 흐름 + +```text +[set_vpd_context 사용자] + │ + ▼ +[역할 permission rule → VPD 권한 필터] + │ + ├──────────────┐ + ▼ ▼ +[TECH_TAG 조건] [VECTOR_DISTANCE + ORDER BY score] + └──────┬───────┘ + ▼ + [effective SQL / Top-K] +``` + +## 4. 데이터/보안 계약 + +- 사용자 입력 평문은 임베딩으로 변환되어 `:embedding` 경계로만 전달된다. 평문·임베딩은 VPD predicate에 섞지 않는다. +- VPD predicate는 DB 함수가 현재 context에서 반환한 값만 표시한다. UI가 임의로 role 조건이나 SQL을 생성하지 않는다. +- `REGEXP_LIKE`는 TAG rule을 저장한 역할이 실제로 effective role에 포함될 때만 나타난다. role/permission이 없으면 fail-closed predicate `1 = 0`이 반환된다. +- `SELECT *`를 사용하지 않고 명시적 컬럼과 score만 반환해 embedding 원문을 노출하지 않는다. + +## 5. 테스트/운영 검증 + +- 템플릿 테스트: 벡터 유사도 기준, 역할 기반 VPD 필터, `VECTOR_DISTANCE`, `ORDER BY score` 문구 확인. +- 전체 테스트: `mvn test`. +- 운영 smoke: `agent_hr`에서 `SPRING_BOOT/ORDS` 권한 필터와 vector score를 함께 확인하고, `agent_all`에서는 전체 TAG rule이 role에 연결된 경우에만 전체 조건이 표시되는지 확인한다. diff --git a/src/main/resources/templates/fragments/probe-result.html b/src/main/resources/templates/fragments/probe-result.html index 17cbd06..c5950a0 100644 --- a/src/main/resources/templates/fragments/probe-result.html +++ b/src/main/resources/templates/fragments/probe-result.html @@ -112,7 +112,10 @@

토큰 적용 후 SQL

-

ORDS Handler가 반환한 VPD predicate 또는 같은 토큰 컨텍스트를 재현해 조회한 predicate를 기본 조회문에 합친 형태입니다.

+

+ ORDS Handler가 반환한 VPD predicate 또는 같은 토큰 컨텍스트를 재현해 조회한 predicate를 기본 조회문에 합친 형태입니다. +

DBMS_RLS predicate
@@ -137,9 +140,17 @@ +
+

벡터 유사도 검색 기준

+
VECTOR_DISTANCE(d.embedding, TO_VECTOR(:embedding), COSINE) AS score
+ORDER BY score ASC
+ROWNUM <= :row_limit
+

이 부분이 검색어 벡터와 저장 벡터의 거리 계산입니다. 아래 권한 필터의 TAG 조건은 검색어 유사도 계산이 아니라 접근 통제입니다.

+
-

VPD가 추가한 WHERE 조건

+

VPD가 추가한 WHERE 조건

(DEPT_CODE = SYS_CONTEXT('CB_AGENT_CTX', 'DEPT_CODE'))
+

선택한 사용자의 직접 역할·그룹 상속 역할에 연결된 permission rule에서 계산된 조건입니다. 권한이 없으면 1 = 0, ALL이면 1 = 1이 됩니다.

권한 적용 SQL

diff --git a/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java b/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java index cf39c09..75ee7ab 100644 --- a/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java +++ b/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java @@ -37,6 +37,9 @@ class GuidedFlowTemplateTest { .contains("토큰 적용 후 SQL") .contains("set_vpd_context 사용자 컨텍스트") .contains("CB_AGENT_CTX.USER_ID") + .contains("벡터 유사도 검색 기준") + .contains("역할 기반 권한 필터 (VPD)") + .contains("VECTOR_DISTANCE") .contains("벡터 검색 Top-K") .contains("벡터 거리 (SCORE)") .contains("vpd_predicate")