# HMM 휴가 원장 팀 계층 VPD 설계 (#707) > 상태: 구현·ADB 적용·배포·검증 완료 > 대상: HMMAIPOC `ADMIN`, `hmm-backoffice.cloud-handson.com` > Git 기준: `hmm-backoffice` ## 목적 HMM 백오피스의 사용자·역할·보호 객체·행 접근 규칙을 실제 Oracle VPD와 연결한다. 팀장 E1001은 자신과 직접 보고 팀원의 휴가 잔여 및 휴가 신청을 조회하고, 일반 팀원은 자기 행만 조회한다. 유효한 사용자 컨텍스트나 허용 규칙이 없으면 모든 행을 차단한다. ## 조사 결과 - 직원 7명은 `HMM_HR_EMPLOYEES`에 있으며 E1001의 직접 보고 관계가 `MANAGER_EMPLOYEE_ID = 1`로 저장되어 있다. - `HMM_LEAVE_BALANCES`는 직원별 1행씩 총 7행이고, `HMM_LEAVE_REQUESTS`는 팀원 6명의 총 8행이다. - HMM 역할 `HMM_HR_VIEWER`, `HMM_HR_MANAGER`, `HMM_HR_ADMIN`은 존재한다. - 적용 전 사용자 역할, HMM 토큰, 보호 객체, 행 접근 규칙, VPD 정책은 0건이었다. - `ADMIN`은 `EXEMPT ACCESS POLICY` 권한이 있어 정책 적용 여부를 검증할 때는 별도의 비면제 검증 사용자가 필요하다. ## 접근 정책 | 사용자 유형 | 역할 | 저장 규칙 | 결과 | |---|---|---|---| | 일반 팀원 | `HMM_HR_VIEWER` | `SELF` | 현재 직원 ID와 같은 `EMPLOYEE_ID` 행 | | 팀장 | `HMM_HR_MANAGER` | `MANAGED_TEAM` | 현재 직원 본인과 `MANAGER_EMPLOYEE_ID`가 현재 직원인 직접 보고자 행 | | HR 관리자 | `HMM_HR_ADMIN` | `ALL` | 전체 행. 역할이 실제로 부여된 경우에만 적용 | | 미인증/무권한 | 없음 | 없음 | `1 = 0` | E1001에는 `HMM_HR_MANAGER`, E1002~E1007에는 `HMM_HR_VIEWER`를 부여한다. HR 관리자 역할은 미리 규칙만 준비하고 현재 데모 사용자에게 자동 부여하지 않는다. ## DB 구성 ### 컨텍스트 `HMM_ACCESS_CTX`는 `HMM_ACCESS_CTX_PKG.SET_USER_BY_BEARER`만이 설정한다. 패키지는 전달된 토큰의 SHA-256 해시를 `HMM_ACCESS_BEARER_TOKENS`와 비교하고 다음 조건을 모두 만족한 경우에만 직원 ID, 사번, 팀 ID를 세션 컨텍스트에 기록한다. - 토큰이 회수되지 않음 - 만료 시각이 현재보다 이후 - 직원이 `ACTIVE` 오류 또는 누락 토큰은 컨텍스트를 먼저 지우고 실패한다. ### 정책 함수 `HMM_LEAVE_VPD_FILTER`는 현재 컨텍스트의 직원에게 직접 또는 접근 그룹으로 부여된 활성 역할을 구한다. 역할과 `CB_PERMISSION`, `CB_PERMISSION_RULE`에 저장된 대상별 규칙을 결합해 `HMM_LEAVE_BALANCES`와 `HMM_LEAVE_REQUESTS`의 `EMPLOYEE_ID` 조건을 반환한다. - 한 권한 안의 규칙은 `AND` - 서로 다른 허용 권한은 `OR` - 거부 규칙은 허용 결과에서 제외 - 알 수 없는 규칙, 존재하지 않는 컬럼, 빈 컨텍스트는 fail-closed ### 정책 연결 두 휴가 테이블에 `HMM_LEAVE_SCOPE_POLICY`를 `SELECT`, `CONTEXT_SENSITIVE`로 연결한다. 정책 메타데이터와 설명은 백오피스의 보호 객체 및 VPD 화면에서 조회한다. ## 백오피스 변경 - `/permissions`가 HMM 역할과 `CB_PERMISSION*` 호환 저장소의 실제 규칙을 표시한다. - HMM 행 규칙 선택지는 `ALL`, `MANAGED_TEAM`, `SELF`, `STATIC_SQL`을 우선 제공한다. - 미리보기는 `HMM_ACCESS_CTX.EMPLOYEE_ID`와 직접 보고 관계를 보여준다. - 휴가 테이블의 기본 정책 연결은 `HMM_LEAVE_VPD_FILTER`를 선택한다. - 보호 객체·역할·권한 수정은 기존 감사 및 외부 권한 변경 알림 흐름을 유지한다. ## 배포 순서 1. 애플리케이션 테스트와 SQL 구문 검사를 수행한다. 2. 멱등 SQL `sql/adb/72_hmm_leave_team_vpd.sql`을 `ADMIN`으로 실행한다. 3. VPD 정책·컴파일 상태·백오피스 화면을 확인한다. 4. 백오피스와 같은 SHA-256 저장 규칙으로 E1001과 E1002 임시 검증 토큰을 만든다. 5. 비면제 검증 사용자에서 토큰별 조회 결과를 확인하고 검증 토큰과 사용자를 제거한다. 6. 애플리케이션 JAR를 배포한 뒤 전 메뉴 회귀검사를 수행한다. ## 완료 기준 - E1001: 휴가 잔여 7행, 휴가 신청 8행 - E1002: 휴가 잔여 1행, 휴가 신청 1행 - E1002가 E1003의 행을 조건에 추가 조회해도 0행 - 무컨텍스트: 두 테이블 모두 0행 - 두 정책과 컨텍스트/패키지/함수가 `VALID` 및 `ENABLE=YES` - `/users`, `/roles`, `/objects`, `/permissions`, `/vpd-policies`, `/vpd-filter-runtime`, `/tokens`, `/probe`를 포함한 백오피스 메뉴에 데이터 처리 오류가 없음 ## 검증 결과 2026-07-23 배포에서 모든 완료 기준을 충족했다. - `HMM_ACCESS_CTX_PKG`와 `HMM_LEAVE_VPD_FILTER`는 `VALID` - 두 `HMM_LEAVE_SCOPE_POLICY`는 `CONTEXT_SENSITIVE`, `ENABLE=YES` - 비면제 임시 DB 사용자와 원문을 저장하지 않는 임시 토큰으로 확인: - 무컨텍스트: 잔여 0행, 신청 0행 - E1001 팀장: 잔여 7행, 신청 8행 - E1002 팀원: 잔여 1행, 신청 1행 - E1002가 E1003 신청을 조건 조회: 0행 - 무효 토큰: 0행 - 검증용 DB 사용자와 임시 토큰은 즉시 제거했다. - 자동 테스트 105건이 통과했다. - 실제 브라우저로 관리 화면 26개와 HMM 정형 원장 6개를 전수 확인했으며 HTTP/화면/브라우저 오류는 0건이었다. 상세 증거는 `docs/reports/2026-07-23-hmm-leave-team-vpd-verification.md`에 기록한다. ## 보안 및 롤백 - 토큰 원문과 DB 비밀번호를 SQL, Git, 로그에 기록하지 않는다. - 검증용 DB 사용자와 검증 토큰은 테스트가 끝나면 제거 또는 회수한다. - 롤백은 두 `HMM_LEAVE_SCOPE_POLICY`를 비활성화하거나 제거한 뒤 사용자 역할·권한 메타데이터를 유지하는 방식으로 수행한다. 휴가 원장 데이터는 수정하거나 삭제하지 않는다.