<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/layout :: head('데이터 접근 제어')}"></head>
<body>
<nav th:replace="~{fragments/layout :: nav}"></nav>
<main class="container py-4 dashboard-page">
  <header class="dashboard-hero">
    <div>
      <span class="architecture-kicker">데이터 접근 제어</span>
      <h1>행 접근과 컬럼 마스킹 운영 흐름</h1>
      <p>업무 사용자와 데이터 접근 기준을 관리하고, DB가 적용한 결과까지 확인합니다.</p>
    </div>
    <div class="dashboard-hero-actions" aria-label="주요 작업">
      <a class="btn rw-btn-primary" href="/users">사용자 관리</a>
      <a class="btn rw-btn-secondary" href="/permissions">행 접근 규칙</a>
    </div>
    <details class="explanation-details dashboard-explanation">
      <summary>도움말: 메뉴와 권한 적용 구조 보기</summary>
      <div class="product-help-overview">
        <section class="product-help-section">
          <h2>왜 권한 테이블을 따로 관리하나요?</h2>
          <p>DB 연결은 공용 실행 계정 하나로 유지하되, 실제 업무 사용자는 <code>CB_APP_USER</code>와 역할·권한 테이블에서 찾습니다. 요청마다 토큰이 사용자를 식별하고 행 접근 정책이 그 사용자의 행 조건을 계산하며, 컬럼 원문/마스킹은 ASO/Data Redaction 정책이 별도로 판단합니다.</p>
        </section>

        <section class="product-help-section">
          <h2>메뉴 안내</h2>
          <dl class="menu-role-grid">
            <div><dt>접근 제어 관리</dt><dd>사용자·그룹·역할과 행 접근 규칙, 컬럼 마스킹 설정을 정하고 최종 적용 결과를 확인합니다.</dd></div>
            <div><dt>보호·검증</dt><dd>보호 정책을 연결하고 토큰으로 실제 DB 조회 결과를 검증합니다.</dd></div>
            <div><dt>연동 도구</dt><dd>조회 대상, ORDS 연동, 지식 검색과 MCP 연결을 관리합니다.</dd></div>
            <div><dt>운영</dt><dd>현재 연결과 실행 상태를 확인합니다.</dd></div>
            <div><dt>관리자</dt><dd>일상 권한 작업과 분리된 시스템 연결, DB 준비, 고급 예외 조건을 관리합니다.</dd></div>
          </dl>
        </section>

        <section class="product-help-section">
          <h2>처음 설정할 때의 순서</h2>
          <p>권한을 먼저 만들고 보호 대상을 연결한 뒤, 실제 사용자 토큰으로 결과를 검증합니다. 권한은 토큰에 복사되지 않아 이후 변경도 다음 요청부터 반영됩니다.</p>
          <div class="diagram-canvas">
            <svg class="product-flow-diagram setup-flow-diagram" viewBox="0 0 1120 245" role="img" aria-labelledby="setup-flow-title setup-flow-desc">
              <title id="setup-flow-title">데이터 접근 제어 설정과 검증 순서</title>
              <desc id="setup-flow-desc">사용자와 그룹, 역할, 행 접근 규칙, 컬럼 마스킹, 보호 대상을 차례로 설정하고 실제 조회 결과를 검증하는 흐름</desc>
              <defs><marker id="setup-flow-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 z"/></marker></defs>
              <path class="diagram-link" marker-end="url(#setup-flow-arrow)" d="M205 100 H238"/>
              <path class="diagram-link" marker-end="url(#setup-flow-arrow)" d="M415 100 H448"/>
              <path class="diagram-link" marker-end="url(#setup-flow-arrow)" d="M625 100 H658"/>
              <path class="diagram-link" marker-end="url(#setup-flow-arrow)" d="M835 100 H868"/>
              <g class="diagram-node diagram-node-step"><rect x="30" y="52" width="175" height="96" rx="12"/><circle cx="57" cy="77" r="15"/><text x="57" y="82" class="diagram-step-number">1</text><text x="117" y="85" class="diagram-node-title">사용자·그룹</text><text x="117" y="113" class="diagram-node-detail">업무 대상을 등록</text></g>
              <g class="diagram-node diagram-node-step"><rect x="240" y="52" width="175" height="96" rx="12"/><circle cx="267" cy="77" r="15"/><text x="267" y="82" class="diagram-step-number">2</text><text x="327" y="85" class="diagram-node-title">역할</text><text x="327" y="113" class="diagram-node-detail">직접·그룹 역할 부여</text></g>
              <g class="diagram-node diagram-node-step diagram-node-accent"><rect x="450" y="52" width="175" height="96" rx="12"/><circle cx="477" cy="77" r="15"/><text x="477" y="82" class="diagram-step-number">3</text><text x="537" y="85" class="diagram-node-title">행 접근 규칙</text><text x="537" y="113" class="diagram-node-detail">객체·행 조건 설정</text></g>
              <g class="diagram-node diagram-node-step diagram-node-accent"><rect x="660" y="52" width="175" height="96" rx="12"/><circle cx="687" cy="77" r="15"/><text x="687" y="82" class="diagram-step-number">4</text><text x="747" y="85" class="diagram-node-title">보호·연결</text><text x="747" y="113" class="diagram-node-detail">정책·ORDS 대상 확인</text></g>
              <g class="diagram-node diagram-node-step diagram-node-data"><rect x="870" y="52" width="220" height="96" rx="12"/><circle cx="897" cy="77" r="15"/><text x="897" y="82" class="diagram-step-number">5</text><text x="977" y="85" class="diagram-node-title">유효 권한·접근 검증</text><text x="977" y="113" class="diagram-node-detail">토큰으로 실제 결과 확인</text></g>
              <path class="setup-flow-return" d="M980 166 V192 H117 V166"/>
              <text x="548" y="218" class="setup-flow-note">규칙 변경은 다음 요청의 행 조건 계산에 동적으로 반영됩니다.</text>
            </svg>
          </div>
        </section>

        <section class="product-help-section">
          <h2>요청마다 권한이 적용되는 흐름</h2>
          <div class="diagram-canvas">
            <svg class="product-flow-diagram" viewBox="0 0 1120 270" role="img" aria-labelledby="vpd-flow-title vpd-flow-desc">
              <title id="vpd-flow-title">행 접근 적용 흐름</title>
              <desc id="vpd-flow-desc">Bearer Token 요청이 공용 실행 계정과 사용자 컨텍스트를 거쳐 권한 테이블에서 계산한 행 조건으로 보호 데이터를 조회하는 흐름</desc>
              <defs><marker id="flow-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 z"/></marker></defs>
              <path class="diagram-link" marker-end="url(#flow-arrow)" d="M190 92 H245"/>
              <path class="diagram-link" marker-end="url(#flow-arrow)" d="M395 92 H450"/>
              <path class="diagram-link" marker-end="url(#flow-arrow)" d="M600 92 H655"/>
              <path class="diagram-link" marker-end="url(#flow-arrow)" d="M805 92 H860"/>
              <path class="diagram-link diagram-link-secondary" marker-end="url(#flow-arrow)" d="M720 210 V143"/>
              <g class="diagram-node"><rect x="30" y="48" width="160" height="88" rx="12"/><text x="110" y="81" class="diagram-node-title">요청·토큰</text><text x="110" y="108" class="diagram-node-detail">Bearer Token</text></g>
              <g class="diagram-node"><rect x="245" y="48" width="150" height="88" rx="12"/><text x="320" y="78" class="diagram-node-title">공용 실행 계정</text><text x="320" y="105" class="diagram-node-detail">CB_ORDS</text><text x="320" y="123" class="diagram-node-note">한 개의 DB 연결</text></g>
              <g class="diagram-node"><rect x="450" y="48" width="150" height="88" rx="12"/><text x="525" y="78" class="diagram-node-title">사용자 컨텍스트</text><text x="525" y="105" class="diagram-node-detail">CB_AGENT_CTX</text><text x="525" y="123" class="diagram-node-note">사용자별로 설정</text></g>
              <g class="diagram-node diagram-node-accent"><rect x="655" y="48" width="150" height="88" rx="12"/><text x="730" y="78" class="diagram-node-title">행 조건 계산</text><text x="730" y="105" class="diagram-node-detail">ALLOW · DENY · predicate</text></g>
              <g class="diagram-node diagram-node-accent"><rect x="860" y="48" width="210" height="88" rx="12"/><text x="965" y="78" class="diagram-node-title">보호 데이터 조회</text><text x="965" y="105" class="diagram-node-detail">허용된 행 반환</text></g>
              <g class="diagram-node diagram-node-data"><rect x="570" y="180" width="300" height="62" rx="12"/><text x="720" y="207" class="diagram-node-title">사용자 · 역할 · 권한 테이블</text><text x="720" y="229" class="diagram-node-detail">요청 시 동적으로 조회</text></g>
            </svg>
          </div>
        </section>

        <section class="product-help-section">
          <h2>권한 데이터 모델</h2>
          <div class="diagram-canvas">
            <svg class="permission-erd-diagram" viewBox="0 0 1180 355" role="img" aria-labelledby="erd-title erd-desc">
              <title id="erd-title">접근 제어 ERD</title>
              <desc id="erd-desc">사용자와 그룹에서 역할을 얻고 역할에서 권한과 권한 규칙을 거쳐 보호 대상으로 연결되는 데이터 모델</desc>
              <defs><marker id="erd-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 z"/></marker></defs>
              <path class="diagram-link" marker-end="url(#erd-arrow)" d="M175 90 H230"/><path class="diagram-link" marker-end="url(#erd-arrow)" d="M390 90 H445"/><path class="diagram-link" marker-end="url(#erd-arrow)" d="M605 90 H660"/><path class="diagram-link" marker-end="url(#erd-arrow)" d="M820 90 H875"/>
              <path class="diagram-link diagram-link-secondary" marker-end="url(#erd-arrow)" d="M175 245 H230"/><path class="diagram-link diagram-link-secondary" marker-end="url(#erd-arrow)" d="M390 245 H445"/><path class="diagram-link diagram-link-secondary" marker-end="url(#erd-arrow)" d="M605 245 V144"/>
              <path class="diagram-link diagram-link-secondary" marker-end="url(#erd-arrow)" d="M100 290 V144"/>
              <g class="erd-entity"><rect x="25" y="50" width="150" height="80" rx="10"/><text x="100" y="80">CB_APP_USER</text><text x="100" y="105">업무 사용자</text></g>
              <g class="erd-entity"><rect x="230" y="50" width="160" height="80" rx="10"/><text x="310" y="80">CB_USER_ROLE</text><text x="310" y="105">직접 역할 연결</text></g>
              <g class="erd-entity"><rect x="445" y="50" width="160" height="80" rx="10"/><text x="525" y="80">CB_APP_ROLE</text><text x="525" y="105">역할</text></g>
              <g class="erd-entity"><rect x="660" y="50" width="160" height="80" rx="10"/><text x="740" y="80">CB_PERMISSION</text><text x="740" y="105">객체 접근</text></g>
              <g class="erd-entity"><rect x="875" y="50" width="160" height="80" rx="10"/><text x="955" y="80">CB_PERMISSION_RULE</text><text x="955" y="105">행 조건 매핑</text></g>
              <g class="erd-entity erd-entity-accent"><rect x="1045" y="50" width="115" height="80" rx="10"/><text x="1102" y="80">보호 대상</text><text x="1102" y="105">TABLE / VIEW</text></g>
              <g class="erd-entity"><rect x="25" y="205" width="150" height="80" rx="10"/><text x="100" y="235">CB_USER_GROUP</text><text x="100" y="260">그룹 소속</text></g>
              <g class="erd-entity"><rect x="230" y="205" width="160" height="80" rx="10"/><text x="310" y="235">CB_GROUP</text><text x="310" y="260">사용자 그룹</text></g>
              <g class="erd-entity"><rect x="445" y="205" width="160" height="80" rx="10"/><text x="525" y="235">CB_GROUP_ROLE</text><text x="525" y="260">그룹 역할 연결</text></g>
              <g class="erd-entity erd-entity-data"><rect x="745" y="205" width="215" height="80" rx="10"/><text x="852" y="235">CB_AGENT_BEARER_KEY</text><text x="852" y="260">토큰 → 사용자 식별</text></g>
            </svg>
          </div>
        </section>

        <section class="product-help-section product-help-sql">
          <h2>실행 SQL은 어디에서 확인하나요?</h2>
          <p><strong>DB 감사 실행 증적</strong>은 FGA가 남긴 실제 실행 SQL과 VPD RLS 정보를 보여줍니다. 화면의 SQL 재현은 설정을 이해하기 위한 참고용이며, 실행 증적과 구분합니다.</p>
        </section>
      </div>
    </details>
  </header>

  <div class="alert alert-warning" th:if="${runtimeErrorMessage}">
    <div class="fw-semibold" th:text="${runtimeErrorTitle}">데이터 처리 오류가 발생했습니다.</div>
    <div th:text="${runtimeErrorMessage}"></div>
    <div class="mt-2" th:if="${showSupportCommand}"><code>./run.sh backoffice-support</code></div>
  </div>

  <section class="content-band">
    <div class="section-heading">
      <div>
        <span class="architecture-kicker">전체 그림</span>
        <h2>토큰은 사용자를 식별하고, DB 정책이 행과 컬럼을 나눠서 제어합니다</h2>
        <p class="section-subtitle">이 백오피스는 토큰 자체에 권한을 복사하지 않습니다. 요청 시점에 토큰으로 사용자를 찾고, 저장된 역할·규칙을 DB 세션 context와 VPD/ASO 정책에 반영합니다.</p>
      </div>
    </div>
    <div class="effective-preview">
      <dl>
        <div>
          <dt>1. 사용자 식별</dt>
          <dd>Bearer Token으로 <code>CB_AGENT_CTX</code>에 사용자·부서·이해관계자 정보를 설정합니다.</dd>
        </div>
        <div>
          <dt>2. 행 접근(VPD)</dt>
          <dd>행 접근 규칙이 대상 테이블의 WHERE predicate로 변환되어 볼 수 있는 행만 남깁니다.</dd>
        </div>
        <div>
          <dt>3. 컬럼 마스킹(ASO)</dt>
          <dd>허용된 행 안에서 민감 컬럼을 원문으로 줄지, 마스킹해서 줄지 결정합니다.</dd>
        </div>
        <div>
          <dt>4. 접근 검증</dt>
          <dd>토큰으로 실제 ORDS 조회를 실행하고, 결과 행·마스킹 컬럼·감사 증적을 확인합니다.</dd>
        </div>
      </dl>
    </div>
  </section>

  <section class="dashboard-menu-flow" aria-labelledby="menu-flow-title">
    <div class="dashboard-section-heading">
      <span class="architecture-kicker">업무 흐름</span>
      <h2 id="menu-flow-title">설정은 접근 제어에서, 적용 확인은 접근 검증에서</h2>
    </div>
    <div class="dashboard-flow-grid">
      <a class="dashboard-flow-card" href="/users"><strong>사용자 관리</strong><span>PoC 운영 사용자를 관리</span></a>
      <a class="dashboard-flow-card" href="/groups"><strong>그룹 관리</strong><span>Data &amp; AI TF 구성</span></a>
      <a class="dashboard-flow-card" href="/roles"><strong>역할 관리</strong><span>운영 역할을 관리</span></a>
      <a class="dashboard-flow-card" href="/permissions"><strong>행 접근 규칙</strong><span>게임 데이터 객체별 접근 규칙</span></a>
    </div>
  </section>

  <section class="dashboard-command-center" aria-label="주요 권한 작업">
    <div class="dashboard-primary-action">
      <h2>바로 시작</h2>
      <ol class="guided-check-list">
        <li><a href="/users">사용자</a>와 <a href="/roles">역할</a>을 준비합니다.</li>
        <li><a href="/permissions">행 접근 규칙</a>에서 역할별 대상 객체와 행 조건을 저장합니다.</li>
        <li><a href="/vpd-policies">보호 상태</a>에서 대상 테이블의 VPD 연결 상태를 확인합니다.</li>
        <li><a href="/masking-rules">컬럼 마스킹</a>에서 민감 컬럼의 ASO 정책을 연결합니다.</li>
        <li><a href="/tokens">검증 세션</a>을 발급하고 <a href="/probe">접근 검증</a>에서 실제 결과를 확인합니다.</li>
      </ol>
      <div class="dashboard-action-grid">
        <a class="dashboard-action" href="/permissions">
          <span><strong>행 접근 규칙</strong><small>역할별 객체·행 조건을 설정합니다. 컬럼은 ASO 마스킹에서 관리합니다.</small></span>
          <span class="dashboard-action-arrow" aria-hidden="true">→</span>
        </a>
        <a class="dashboard-action dashboard-action-emphasis" href="/probe">
          <span><strong>접근 검증</strong><small>검증 세션으로 실제 DB 조회 결과를 확인합니다.</small></span>
          <span class="dashboard-action-arrow" aria-hidden="true">→</span>
        </a>
      </div>
    </div>
    <aside class="dashboard-state" aria-label="현재 설정 현황">
      <span class="architecture-kicker">현재 상태</span>
      <dl>
        <div><dt>보호 객체</dt><dd th:text="${#lists.size(objects)}">0</dd></div>
        <div><dt>역할</dt><dd th:text="${#lists.size(roles)}">0</dd></div>
        <div><dt>검증 세션</dt><dd th:text="${#lists.size(tokens)}">0</dd></div>
      </dl>
      <a href="/objects">등록 대상 보기 <span aria-hidden="true">→</span></a>
    </aside>
  </section>

  <details class="dashboard-details">
    <summary>등록 대상 상세</summary>
    <div class="dashboard-details-body">
      <section class="dashboard-object-list">
        <div class="section-heading">
          <div>
            <h2>현재 검증 가능한 데이터</h2>
            <p class="section-subtitle">행 접근 규칙과 ORDS 경로가 등록된 보호 객체입니다.</p>
          </div>
          <a class="btn btn-sm rw-btn-primary" href="/probe">접근 검증</a>
        </div>
        <div class="table-responsive">
          <table class="table table-sm align-middle">
            <thead><tr><th>데이터 객체</th><th>검증 경로</th><th>상태</th></tr></thead>
            <tbody>
            <tr th:each="object : ${objects}">
              <td><strong th:text="${object.displayName()}">ADMIN.OBJECT</strong></td>
              <td><code th:text="${object.ordsPath()}">path</code></td>
              <td><span class="badge text-bg-success">사용 가능</span></td>
            </tr>
            <tr th:if="${#lists.isEmpty(objects)}"><td colspan="3" class="text-muted">아직 검증할 보호 객체가 없습니다. 행 접근 규칙에서 객체 접근을 먼저 등록하세요.</td></tr>
            </tbody>
          </table>
        </div>
      </section>
    </div>
  </details>
</main>
</body>
</html>
