From fb9378192511be9939b82a6163c45ee58cb1380e Mon Sep 17 00:00:00 2001 From: devmrko Date: Tue, 30 Jun 2026 14:29:54 +0900 Subject: [PATCH] [Developer] #571 show VPD context in SQL trace --- docs/design/571-vpd-context-trace/README.md | 47 +++++++++++++++++++ .../templates/fragments/probe-result.html | 20 ++++++++ .../web/GuidedFlowTemplateTest.java | 2 + 3 files changed, 69 insertions(+) create mode 100644 docs/design/571-vpd-context-trace/README.md diff --git a/docs/design/571-vpd-context-trace/README.md b/docs/design/571-vpd-context-trace/README.md new file mode 100644 index 0000000..4ae19bc --- /dev/null +++ b/docs/design/571-vpd-context-trace/README.md @@ -0,0 +1,47 @@ +# 설계서: SQL trace의 set_vpd_context 사용자 컨텍스트 표시 (#571) + +> **상태**: Approved +> **작성**: [AI] Architect · **최종수정**: 2026-06-30 +> **추적성** — Redmine: #571 · 선행 기능: #567, #570 +> · 구현 파일: `probe-result.html`, `TokenContextView`, `ProbeController` +> · 테스트: `GuidedFlowTemplateTest`, `mvn test` + +## 1. 목적 + +권한 적용 SQL trace에서 최종 predicate만 보여 사용자와 predicate의 연결이 끊겨 보이는 문제를 해결한다. `set_vpd_context`가 설정한 `CB_AGENT_CTX.USER_ID`와 백오피스가 해석한 사용자·역할·그룹을 predicate 앞에 표시해 다음 흐름을 한 화면에서 증명한다. + +```text +Bearer Token + → set_vpd_context + → CB_AGENT_CTX.USER_ID = 사용자 ID + → 사용자/역할/그룹 권한 규칙 조회 + → VPD predicate + → effective SQL +``` + +## 2. 설계 원칙 + +- SQL에 `AND USER_ID = ...` 같은 가짜 조건을 추가하지 않는다. 벡터 검색 대상에는 `USER_ID` 컬럼이 없고, 실제 VPD 함수는 사용자 context로 권한 규칙을 계산한 뒤 대상 데이터의 `TECH_TAG` predicate를 반환한다. +- context는 실제 토큰에서 해석된 `TokenContextView`를 사용한다. Bearer 원문은 표시하지 않는다. +- `USER_ID`, 사용자명, 직접 역할, 그룹, 상속 역할은 trace 영역의 “set_vpd_context 사용자 컨텍스트” 카드에 표시한다. +- 아래 VPD predicate는 바로 위 context에서 계산된 결과라는 설명을 명시한다. + +## 3. 인수조건 + +- [ ] `토큰 적용 후 SQL`에 `CB_AGENT_CTX.USER_ID`와 사용자명이 표시된다. +- [ ] 직접 역할·그룹·상속 역할이 context 카드에서 확인된다. +- [ ] context → `VPD가 추가한 WHERE 조건` → `권한 적용 SQL` 순서가 화면에 보인다. +- [ ] SQL 본문에 실제 존재하지 않는 `USER_ID` 조건을 삽입하지 않는다. +- [ ] invalid/inactive token처럼 context가 없을 때는 기존 “토큰에서 사용자를 찾지 못함” 안내를 유지한다. +- [ ] Bearer 원문과 임베딩 숫자는 context 카드에 표시하지 않는다. +- [ ] 전체 Maven 테스트와 실제 vector probe smoke가 통과한다. + +## 4. 화면 계약 + +`TokenContextView.userId()`를 `CB_AGENT_CTX.USER_ID` 값으로 표시하고, `username`, `directRoles`, `groups`, `inheritedRoles`를 사람이 읽을 수 있는 label로 표시한다. predicate와 effective SQL은 기존 `ProbeResult` 필드를 그대로 사용한다. + +## 5. 검증 + +- 템플릿 테스트에서 `set_vpd_context 사용자 컨텍스트`, `CB_AGENT_CTX.USER_ID`, `VPD가 추가한 WHERE 조건`, `권한 적용 SQL`을 확인한다. +- `mvn test`. +- vector `/probe`에서 `agent_all` 또는 선택 사용자의 ID/역할과 TAG predicate가 같은 결과 카드에 표시되는지 확인한다. diff --git a/src/main/resources/templates/fragments/probe-result.html b/src/main/resources/templates/fragments/probe-result.html index 64ebc35..17cbd06 100644 --- a/src/main/resources/templates/fragments/probe-result.html +++ b/src/main/resources/templates/fragments/probe-result.html @@ -117,6 +117,26 @@ DBMS_RLS predicate
+
+

set_vpd_context 사용자 컨텍스트

+

이 컨텍스트로 권한 규칙을 계산한 뒤 아래 VPD predicate와 effective SQL을 만들었습니다.

+
+
CB_AGENT_CTX.USER_ID
103
+
사용자
agent_all
+
+
직접 역할
+
ALL_DOC_ROLE
+
+
+
소속 그룹
+
없음
+
+
+
상속 역할
+
없음
+
+
+

VPD가 추가한 WHERE 조건

(DEPT_CODE = SYS_CONTEXT('CB_AGENT_CTX', 'DEPT_CODE'))
diff --git a/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java b/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java index 6bce594..cf39c09 100644 --- a/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java +++ b/src/test/java/com/cloudhandson/vpdbackoffice/web/GuidedFlowTemplateTest.java @@ -35,6 +35,8 @@ class GuidedFlowTemplateTest { assertThat(result) .contains("적용된 사용자와 권한") .contains("토큰 적용 후 SQL") + .contains("set_vpd_context 사용자 컨텍스트") + .contains("CB_AGENT_CTX.USER_ID") .contains("벡터 검색 Top-K") .contains("벡터 거리 (SCORE)") .contains("vpd_predicate")