ui: remove source dataset selector from DDS flow
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
<a class="journey-card" href="/vpd-policies"><span class="journey-number">2</span><div><h2>2. DDS 보호 연결</h2><p>공통 규칙을 DDS 전용 VIEW와 DATA GRANT에 연결합니다.</p><strong>DDS 보호 객체 확인 →</strong></div></a>
|
||||
<a class="journey-card" href="/dds-provision"><span class="journey-number">3</span><div><h2>3. DDS 권한 연결</h2><p>보호 VIEW별 DATA GRANT와 공통 권한 predicate를 확인합니다.</p><strong>Grant 미리보기·게시 →</strong></div></a>
|
||||
<a class="journey-card" href="/vector-knowledge"><span class="journey-number">4</span><div><h2>4. 토큰 권한 검색</h2><p>하나의 기술 사용자에 Bearer 토큰을 연결해 공통 권한을 적용합니다.</p><strong>토큰 기반 검색 →</strong></div></a>
|
||||
<a class="journey-card" href="/dds"><span class="journey-number">5</span><div><h2>5. 직접 END USER 비교</h2><p>저수준 DDS END USER·DATA ROLE 결과를 별도로 확인합니다.</p><strong>직접 조회 실행 →</strong></div></a>
|
||||
<a class="journey-card" href="/dds"><span class="journey-number">5</span><div><h2>5. 보호 객체 구조</h2><p>테이블·컬럼·분류값 단위의 DDS 적용 범위를 확인합니다.</p><strong>보호 구조 보기 →</strong></div></a>
|
||||
</section>
|
||||
|
||||
<section class="content-band macro-micro-grid">
|
||||
@@ -40,7 +40,6 @@
|
||||
<div class="section-heading"><div><h2>현재 DDS 검증 대상</h2><p class="section-subtitle">주 시나리오는 업무 분류값이 붙은 벡터 지식자료 검색입니다. 원본 테이블은 보조 기술 검증으로만 제공합니다.</p></div></div>
|
||||
<div class="table-responsive"><table class="table table-sm align-middle"><thead><tr><th>대상</th><th>보호 방식</th><th>검증</th></tr></thead><tbody>
|
||||
<tr><td><code th:text="${vectorObject}">ADMIN.CB_DDS_VECTOR_SEARCH_DOCUMENTS</code></td><td>객체별 분류값 DATA GRANT + 토큰 Context + VECTOR_DISTANCE</td><td><a href="/vector-knowledge">지식 검색</a></td></tr>
|
||||
<tr><td>PG/MY 원본 예제</td><td>보조 END USER 직접 Grant</td><td><a href="/dds">저수준 검증 열기</a></td></tr>
|
||||
</tbody></table></div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@@ -1,156 +1,90 @@
|
||||
<!doctype html>
|
||||
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
|
||||
<head th:replace="~{fragments/layout :: head('DDS 직접 조회 검증')}"></head>
|
||||
<head th:replace="~{fragments/layout :: head('DDS 지식 권한 구조')}"></head>
|
||||
<body>
|
||||
<nav th:replace="~{fragments/layout :: nav}"></nav>
|
||||
|
||||
<main class="container py-4">
|
||||
<header class="hero">
|
||||
<span class="eyebrow">DEEP DATA SECURITY · INDEPENDENT DEMO</span>
|
||||
<h1>업무 사용자의 지식 접근 범위를 DDS로 확인합니다.</h1>
|
||||
<p class="lead">이 화면은 VPD 데모와 별도로 실행되는 DDS 보조 검증 화면입니다. 실제 시나리오는 세일즈 사용자의 토큰이 `TECH_TAG=SALES`인 지식 청크만 검색하도록 제한하는 것입니다.</p>
|
||||
<span class="eyebrow">DEEP DATA SECURITY · KNOWLEDGE POLICY</span>
|
||||
<h1>업무 사용자의 지식 접근 범위를 DDS로 제한합니다.</h1>
|
||||
<p class="lead">이 화면의 보호 대상은 PG나 MY 원본이 아닙니다. 벡터화된 지식 청크를 담은 하나의 보호 VIEW와 그 안의 업무 분류값을 대상으로 합니다.</p>
|
||||
<details class="explanation">
|
||||
<summary>이 화면의 보안 경계</summary>
|
||||
<p>문서를 청킹·임베딩할 때 각 청크의 <code>TECH_TAG</code>에 업무 분류값을 저장합니다. 권한 관리에서는 역할에 허용할 값을 등록하고, DDS Data Grant가 보호 VIEW의 해당 컬럼 값을 predicate로 평가합니다.</p>
|
||||
<p class="mb-0">예를 들어 세일즈 사용자의 토큰이 업무 사용자 <code>agent_sales</code>로 매핑되고 역할에 <code>ALLOW TAG SALES</code>가 있으면, 검색 결과에는 <code>TECH_TAG</code>에 SALES가 포함된 청크만 남습니다.</p>
|
||||
<summary>세일즈 시나리오 설명</summary>
|
||||
<p>세일즈 사용자의 Bearer 토큰은 공통 권한 테이블의 <code>agent_sales</code>로 매핑됩니다. 역할에 <code>ALLOW TAG SALES</code>가 있으면 보호 VIEW의 <code>TECH_TAG</code> 값에 SALES가 포함된 청크만 DDS Data Grant를 통과합니다.</p>
|
||||
<p class="mb-0">문서가 벡터로 검색된다는 점은 검색 방식이고, 어떤 사용자가 볼 수 있는지는 청크에 저장된 분류값과 권한 규칙이 결정합니다.</p>
|
||||
</details>
|
||||
</header>
|
||||
|
||||
<section th:replace="~{fragments/layout :: architectureStrip('token')}"></section>
|
||||
|
||||
<section class="flow-grid" aria-label="DDS 접근 흐름">
|
||||
<section class="flow-grid" aria-label="DDS 지식 접근 흐름">
|
||||
<article class="flow-card">
|
||||
<span class="flow-number">1</span>
|
||||
<div><span class="eyebrow">IDENTITY</span><h2>업무 사용자 토큰</h2><p>Bearer 토큰을 세일즈 업무 사용자로 매핑합니다.</p></div>
|
||||
</article>
|
||||
<article class="flow-card">
|
||||
<span class="flow-number">2</span>
|
||||
<div><span class="eyebrow">POLICY</span><h2>객체별 DATA GRANT</h2><p>보호 VIEW의 컬럼 값과 공통 권한 규칙을 연결합니다.</p></div>
|
||||
<div><span class="eyebrow">POLICY</span><h2>객체별 DATA GRANT</h2><p>보호 VIEW의 행 조건과 컬럼 범위를 선언합니다.</p></div>
|
||||
</article>
|
||||
<article class="flow-card">
|
||||
<span class="flow-number">3</span>
|
||||
<div><span class="flow-number result-number">3</span><span class="eyebrow">EVIDENCE</span><h2>허용된 지식</h2><p>SALES 값이 붙은 청크만 벡터 검색 결과로 반환됩니다.</p></div>
|
||||
<div><span class="flow-number result-number">3</span><span class="eyebrow">VALUE</span><h2>TECH_TAG 값</h2><p>SALES가 포함된 청크만 남깁니다.</p></div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<span class="eyebrow">SAME MANAGEMENT FLOW</span>
|
||||
<h2>VPD 데모와 같은 권한 관리 흐름</h2>
|
||||
<p>사용자·그룹·역할·데이터 권한은 같은 순서로 설계하고, 문서 청크의 분류값과 보호 VIEW를 DDS Data Grant로 연결합니다.</p>
|
||||
<span class="eyebrow">BUSINESS SCENARIO</span>
|
||||
<h2>세일즈 사용자의 지식 검색</h2>
|
||||
<p>권한 관리에서 정의한 사용자·역할·규칙이 벡터 지식 검색 결과에 어떻게 적용되는지 확인합니다.</p>
|
||||
</div>
|
||||
<a class="btn btn-primary" href="/vector-knowledge">토큰 지식 검색 열기</a>
|
||||
</div>
|
||||
<div class="matrix-grid">
|
||||
<a class="matrix-card" href="/users"><strong>1. 사용자</strong><span>누가 요청하는가</span><small>애플리케이션 사용자와 DDS END USER의 관계를 확인합니다.</small></a>
|
||||
<a class="matrix-card" href="/groups"><strong>2. 그룹·역할</strong><span>어떤 업무 범위인가</span><small>그룹과 역할 상속을 같은 관리 화면에서 설정합니다.</small></a>
|
||||
<a class="matrix-card" href="/permissions"><strong>3. 데이터 권한</strong><span>어떤 행·컬럼인가</span><small>행 규칙과 태그 기준을 관리 정책으로 정의합니다.</small></a>
|
||||
<a class="matrix-card" href="/effective-matrix"><strong>4. 최종 권한</strong><span>DDS 적용 대상 확인</span><small>역할별 결과를 확인한 뒤 DATA ROLE/GRANT로 반영합니다.</small></a>
|
||||
<div class="matrix-card"><strong>업무 사용자</strong><span>agent_sales</span><small>SALES 부서 · Bearer 토큰으로 식별</small></div>
|
||||
<div class="matrix-card"><strong>역할</strong><span>SALES_KNOWLEDGE_ROLE</span><small>세일즈 지식 접근 역할</small></div>
|
||||
<div class="matrix-card"><strong>규칙</strong><span>ALLOW TAG SALES</span><small>TECH_TAG 컬럼 값에 SALES 포함</small></div>
|
||||
<div class="matrix-card"><strong>결과</strong><span>청크 28004</span><small>세일즈 파이프라인 운영 가이드만 반환</small></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="alert alert-warning" th:if="${configuredUserCount == 0}">
|
||||
DDS 직접 비교 사용자의 비밀번호가 설정되지 않았습니다. 주 시나리오인 토큰 검색은 <code>/vector-knowledge</code>에서 기술 사용자 설정을 별도로 확인합니다.
|
||||
</div>
|
||||
|
||||
<details class="explanation mb-4">
|
||||
<summary>저수준 PG/MY DDS 예제 열기</summary>
|
||||
<section class="panel">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<span class="eyebrow">1 · SECURITY SUBJECT</span>
|
||||
<h2>저수준 DDS 직접 검증</h2>
|
||||
<p>PG/MY는 제품 시나리오가 아니라 DDS의 객체별 직접 Grant 동작을 확인하기 위한 보조 예제입니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" action="/dds/query" class="query-grid">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<label>
|
||||
DDS END USER
|
||||
<select class="form-select" name="userKey" required>
|
||||
<option th:each="user : ${users}" th:value="${user.key()}" th:selected="${user.key() == selectedUser}"
|
||||
th:text="${user.label() + ' · ' + user.username()}"></option>
|
||||
</select>
|
||||
<span class="field-help" th:each="user : ${users}" th:if="${user.key() == selectedUser}" th:text="${user.description()}"></span>
|
||||
</label>
|
||||
<label>
|
||||
보호 데이터 원본
|
||||
<select class="form-select" name="sourceKey" required>
|
||||
<option th:each="source : ${sources}" th:value="${source.key()}" th:selected="${source.key() == selectedSource}"
|
||||
th:text="${source.label()}"></option>
|
||||
</select>
|
||||
<span class="field-help" th:each="source : ${sources}" th:if="${source.key() == selectedSource}" th:text="${source.objectName()}"></span>
|
||||
</label>
|
||||
<label>
|
||||
이름 검색 (선택)
|
||||
<input class="form-control" name="searchText" placeholder="예: Alice">
|
||||
<span class="field-help">검색 조건도 보호 VIEW 안에서만 평가됩니다.</span>
|
||||
</label>
|
||||
<label>
|
||||
최대 행 수
|
||||
<input class="form-control" name="limit" type="number" min="1" max="100" value="20">
|
||||
</label>
|
||||
<div class="query-submit"><button class="btn btn-primary" type="submit">DDS 권한으로 조회</button></div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<span class="eyebrow">2 · EXPECTED MATRIX</span>
|
||||
<h2>보조 원본 권한 매트릭스</h2>
|
||||
<p>아래 PG/MY 매트릭스는 지식 검색 시나리오와 분리된 DDS 저수준 테스트 데이터입니다.</p>
|
||||
<span class="eyebrow">PROTECTED OBJECT</span>
|
||||
<h2>테이블·컬럼·값 단위의 보호 범위</h2>
|
||||
<p>지식 검색 VIEW와 그 안의 분류 컬럼 값을 기준으로 판단합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="matrix-grid">
|
||||
<div class="matrix-card"><strong>dds_demo_my</strong><span>MY 데이터셋 허용</span><small>PG 객체는 ORA-00942</small></div>
|
||||
<div class="matrix-card"><strong>dds_demo_pg</strong><span>PG 데이터셋 허용</span><small>MY 객체는 ORA-00942</small></div>
|
||||
<div class="matrix-card"><strong>dds_demo_both</strong><span>PG + MY 허용</span><small>두 DATA GRANT 모두 적용</small></div>
|
||||
<div class="matrix-card muted"><strong>dds_demo_none</strong><span>접속만 허용</span><small>데이터 권한 없음 · default deny</small></div>
|
||||
</div>
|
||||
</section>
|
||||
</details>
|
||||
|
||||
<section class="panel" th:if="${queryResult != null}">
|
||||
<div class="panel-heading result-heading">
|
||||
<div>
|
||||
<span class="eyebrow">3 · EVIDENCE</span>
|
||||
<h2 th:text="${queryResult.userLabel() + ' · ' + queryResult.sourceLabel()}">조회 결과</h2>
|
||||
<p th:text="${queryResult.objectName()}">ADMIN.V_DDS_CUSTOMERS_PG</p>
|
||||
</div>
|
||||
<span class="result-status" th:classappend="${queryResult.success()} ? ' success' : ' blocked'"
|
||||
th:text="${queryResult.success()} ? '정책 적용됨' : '접근 차단'">상태</span>
|
||||
</div>
|
||||
<div class="alert" th:classappend="${queryResult.success()} ? ' alert-success' : ' alert-warning'">
|
||||
<strong th:text="${queryResult.title()}">결과</strong>
|
||||
<span th:text="${queryResult.message()}">메시지</span>
|
||||
<span th:if="${queryResult.oracleCode() != null}" class="technical-code" th:text="${'Oracle code: ' + queryResult.oracleCode()}"></span>
|
||||
</div>
|
||||
<div class="context-grid" th:if="${queryResult.success()}">
|
||||
<div><span>SESSION_USER</span><strong th:text="${queryResult.sessionUser() ?: '-'}">-</strong></div>
|
||||
<div><span>ORA_END_USER_CONTEXT</span><strong th:text="${queryResult.endUser() ?: '-'}">-</strong></div>
|
||||
<div><span>반환 행</span><strong th:text="${#lists.size(queryResult.rows())}">0</strong></div>
|
||||
</div>
|
||||
<div class="table-responsive" th:if="${queryResult.success() and queryResult.hasRows()}">
|
||||
<div class="table-responsive">
|
||||
<table class="table align-middle">
|
||||
<thead><tr><th>ID</th><th>이름</th><th>이메일</th><th>가입일</th><th>지역</th></tr></thead>
|
||||
<thead><tr><th>구성</th><th>현재 예제</th><th>권한 판단</th></tr></thead>
|
||||
<tbody>
|
||||
<tr th:each="row : ${queryResult.rows()}">
|
||||
<td th:text="${row.customerId()}">1</td>
|
||||
<td th:text="${row.fullName()}">Alice</td>
|
||||
<td th:text="${row.email() ?: 'NULL'}">alice@example.com</td>
|
||||
<td th:text="${row.signupDate() ?: '-'}">2026-01-01</td>
|
||||
<td th:text="${row.region()}">APAC</td>
|
||||
</tr>
|
||||
<tr><td>보호 객체</td><td><code th:text="${vectorObject}">ADMIN.CB_DDS_VECTOR_SEARCH_DOCUMENTS</code></td><td>객체별 DATA GRANT</td></tr>
|
||||
<tr><td>행 판단 컬럼</td><td><code>TECH_TAG</code></td><td>값에 SALES 포함 여부</td></tr>
|
||||
<tr><td>업무 규칙</td><td><code>ALLOW TAG SALES</code></td><td>공통 CB_PERMISSION_RULE에서 조회</td></tr>
|
||||
<tr><td>검색 컬럼</td><td><code>EMBEDDING</code></td><td>거리 계산에 사용하며 응답에는 반환하지 않음</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="empty-result" th:if="${queryResult.success() and !queryResult.hasRows()}">조회 조건을 통과한 행이 없습니다.</div>
|
||||
<details class="explanation">
|
||||
<summary>판정 근거와 운영 메모</summary>
|
||||
<p>성공한 경우 연결 시점의 <code>SESSION_USER</code>와 <code>ORA_END_USER_CONTEXT</code>를 함께 확인할 수 있습니다. 차단된 경우 DDS가 보호 객체 자체를 숨겨 <code>ORA-00942</code>를 반환하는 것이 정상입니다.</p>
|
||||
<p class="mb-0">현재 앱은 결과만 읽습니다. 권한 변경은 <code>CREATE DATA ROLE</code>, <code>GRANT DATA ROLE</code>, <code>CREATE DATA GRANT</code> 승인 절차를 거쳐 SQL로 관리합니다.</p>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<span class="eyebrow">IMPLEMENTATION</span>
|
||||
<h2>추가·수정할 때의 기준</h2>
|
||||
</div>
|
||||
</div>
|
||||
<ol>
|
||||
<li>문서 청킹·임베딩 시 청크에 업무 분류값을 저장합니다. 예: <code>SALES</code>, <code>HR</code>, <code>FINANCE</code>.</li>
|
||||
<li>권한 관리에서 역할에 허용할 분류값을 <code>TAG</code> 규칙으로 등록합니다.</li>
|
||||
<li>보호 VIEW별 Data Grant predicate가 해당 컬럼 값을 공통 권한체계와 비교합니다.</li>
|
||||
<li>세일즈 토큰, 다른 부서 토큰, invalid token으로 결과를 회귀 검증합니다.</li>
|
||||
</ol>
|
||||
<p class="mb-0"><a href="/permissions">권한 관리</a>에서 규칙을 확인하고, <a href="/vector-knowledge">지식 검색</a>에서 실제 반환 청크를 확인하세요.</p>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user