Compare commits
2 Commits
8978be4182
...
ef7a855462
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef7a855462 | ||
|
|
fb93781925 |
@@ -1,7 +1,7 @@
|
|||||||
# 설계서: 기술 태그 기반 벡터 지식자료 검색과 VPD 연결
|
# 설계서: 기술 태그 기반 벡터 지식자료 검색과 VPD 연결
|
||||||
|
|
||||||
> **상태**: 제품형 운영 흐름 구현 · DDS 병행 검증 완료 · 객체별 Data Grant predicate 적용 · 운영 확장 항목 별도
|
> **상태**: 제품형 운영 흐름 구현 · DDS 병행 검증 완료 · 객체별 Data Grant predicate 적용 · 운영 확장 항목 별도
|
||||||
> **추적성**: Redmine #565, #566 · 구현 커밋 `a5e70bc` · 기준 구현: `28_agent_ords_vector_tag_vpd_setup.sql`, `29_agent_ords_vector_search_ords.sql`, `32_dds_vector_tag_setup.sql`, `34_dds_token_data_grant_common_auth.sql`, `36_dds_sales_knowledge_scenario.sql`
|
> **추적성**: Redmine #565, #566 · 구현 커밋 `a5e70bc`, `04cca64`, `8978be4` · 기준 구현: `28_agent_ords_vector_tag_vpd_setup.sql`, `29_agent_ords_vector_search_ords.sql`, `32_dds_vector_tag_setup.sql`, `34_dds_token_data_grant_common_auth.sql`, `36_dds_sales_knowledge_scenario.sql`
|
||||||
|
|
||||||
## 1. 한 문장으로 이해하기
|
## 1. 한 문장으로 이해하기
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 독립 VPD·DDS 데모 구성
|
# 독립 VPD·DDS 데모 구성
|
||||||
|
|
||||||
> **상태**: VPD·DDS 병행 검증 완료, 토큰 기반 객체별 Data Grant 적용 완료
|
> **상태**: VPD·DDS 병행 검증 완료, 토큰 기반 객체별 Data Grant 적용 완료
|
||||||
> **추적성**: Redmine #565, #566 · DDS 구현 커밋 `1e48864`, `a5e70bc`
|
> **추적성**: Redmine #565, #566 · DDS 구현 커밋 `1e48864`, `a5e70bc`, `04cca64`, `8978be4`
|
||||||
> **기준 구현**: `sql/adb/32_dds_vector_tag_setup.sql`, `sql/adb/34_dds_token_data_grant_common_auth.sql`, `sql/adb/36_dds_sales_knowledge_scenario.sql`, `dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/service/DdsGrantPublisher.java`, `dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/service/DdsVectorKnowledgeService.java`
|
> **기준 구현**: `sql/adb/32_dds_vector_tag_setup.sql`, `sql/adb/34_dds_token_data_grant_common_auth.sql`, `sql/adb/36_dds_sales_knowledge_scenario.sql`, `dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/service/DdsGrantPublisher.java`, `dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/service/DdsVectorKnowledgeService.java`
|
||||||
|
|
||||||
## 목적
|
## 목적
|
||||||
|
|||||||
47
docs/design/571-vpd-context-trace/README.md
Normal file
47
docs/design/571-vpd-context-trace/README.md
Normal file
@@ -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가 같은 결과 카드에 표시되는지 확인한다.
|
||||||
@@ -117,6 +117,26 @@
|
|||||||
<span class="badge text-bg-light">DBMS_RLS predicate</span>
|
<span class="badge text-bg-light">DBMS_RLS predicate</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="probe-exchange-grid mt-3">
|
<div class="probe-exchange-grid mt-3">
|
||||||
|
<section class="probe-exchange" data-sql-trace-field="vpd_context" th:if="${tokenContext}">
|
||||||
|
<h3>set_vpd_context 사용자 컨텍스트</h3>
|
||||||
|
<p class="form-hint">이 컨텍스트로 권한 규칙을 계산한 뒤 아래 VPD predicate와 effective SQL을 만들었습니다.</p>
|
||||||
|
<dl class="mb-0">
|
||||||
|
<div><dt>CB_AGENT_CTX.USER_ID</dt><dd th:text="${tokenContext.userId()}">103</dd></div>
|
||||||
|
<div><dt>사용자</dt><dd th:text="${tokenContext.username()}">agent_all</dd></div>
|
||||||
|
<div>
|
||||||
|
<dt>직접 역할</dt>
|
||||||
|
<dd th:text="${#lists.isEmpty(tokenContext.directRoles()) ? '없음' : #strings.listJoin(tokenContext.directRoles(), ', ')}">ALL_DOC_ROLE</dd>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<dt>소속 그룹</dt>
|
||||||
|
<dd th:text="${#lists.isEmpty(tokenContext.groups()) ? '없음' : #strings.listJoin(tokenContext.groups(), ', ')}">없음</dd>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<dt>상속 역할</dt>
|
||||||
|
<dd th:text="${#lists.isEmpty(tokenContext.inheritedRoles()) ? '없음' : #strings.listJoin(tokenContext.inheritedRoles(), ', ')}">없음</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
</section>
|
||||||
<section class="probe-exchange" data-sql-trace-field="vpd_predicate">
|
<section class="probe-exchange" data-sql-trace-field="vpd_predicate">
|
||||||
<h3>VPD가 추가한 WHERE 조건</h3>
|
<h3>VPD가 추가한 WHERE 조건</h3>
|
||||||
<pre th:text="${result.vpdPredicate()}">(DEPT_CODE = SYS_CONTEXT('CB_AGENT_CTX', 'DEPT_CODE'))</pre>
|
<pre th:text="${result.vpdPredicate()}">(DEPT_CODE = SYS_CONTEXT('CB_AGENT_CTX', 'DEPT_CODE'))</pre>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ class GuidedFlowTemplateTest {
|
|||||||
assertThat(result)
|
assertThat(result)
|
||||||
.contains("적용된 사용자와 권한")
|
.contains("적용된 사용자와 권한")
|
||||||
.contains("토큰 적용 후 SQL")
|
.contains("토큰 적용 후 SQL")
|
||||||
|
.contains("set_vpd_context 사용자 컨텍스트")
|
||||||
|
.contains("CB_AGENT_CTX.USER_ID")
|
||||||
.contains("벡터 검색 Top-K")
|
.contains("벡터 검색 Top-K")
|
||||||
.contains("벡터 거리 (SCORE)")
|
.contains("벡터 거리 (SCORE)")
|
||||||
.contains("vpd_predicate")
|
.contains("vpd_predicate")
|
||||||
|
|||||||
Reference in New Issue
Block a user