HBAD220_역할 관리·권한 트리
(Hereby) 관리자 패널 > 인사 관리 > 역할 관리
| 메타 | 앱: 관리자 패널 (포트 4001)대상 사용자: 조건1 [최고 관리자] / 조건2 [인사 관리자] (권한 "역할 관리")프로토타입: TBU관련 정책: [[POL_권한(RBAC)]] · [[POL_역할 관리]] · [[POL_급여정본경계]]Status: reviewOwner: 카나 |
개요
역할 관리는 테넌트 커스텀 역할(roles)과 세분화 권한 트리(permissions — 리소스 × 액션 × scope)를 관리한다. 역할 카드 목록 + 역할 추가/수정 모달(권한 선택 트리)로 구성된다. 권한은 리소스(약 33종) × 액션(관리/조회/수정/승인/계산) × scope(본인/팀/전체) 조합의 PermissionToken이다 (예: 급여담당 매니저 = 53개 권한 선택됨). 권한 라벨 ↔ 급여 시트(HBHR) 매핑: 전체확정 → "급여 승인", 컬럼 계산 → "급여 계산", 시트 편집 → "급여 관리", 조회 → "급여 조회" ([[POL_급여정본경계]]). 내부 토큰 key(payroll:*)는 추정.
문서 히스토리
- 2026-07-06 최초 작성 - 카나/콸
- 2026-07-13 버튼 행동 명세 보강 - 카나/콸
- 2026-07-21 GC700 깊이 재작성 (권한 트리 n/m 카운터 프로브 반영) - 카나/콸
- 2026-07-21 셀 스타일 확정판 적용 (콸 승인) - 카나/PM
- 2026-09-11 역할 목록 기본 상태 필터 "활성" 반영(#665 머지) — 진입 시 활성 역할만 노출. 목록 기본 정렬은 라이브 실증 불가(4역할 전부 활성)로 TBU 유지. 근거 = 커밋(#665) - 카나/PM
- 2026-09-14 부서 · 팀(병동) 선택 입력(중복 선택)과 목록 필터 추가
- 2026-09-26 개발측 직접 보강(9/14 부서·팀(병동) 지정·목록 필터 ㄴ15/ㄴ16·21/22) 미러·컨플 부본에 역수용 — 정본(docs/spec) 우선 - 카나/PM
- 2026-09-29 ward 권한 리소스 신설 반영(#833/#912, 마이그 1927 — ward.manage/ward.read, 「병동 페이지 관리자」) — 라이브 실측: 권한 트리에 i18n 키 원문("perm.resource.ward…")으로 노출되는 locale 누락 버그 발견, OQ 기록 - 카나/PM
- 2026-09-30 ward 라벨 locale 버그 해소(#945)·aiApp/연차 촉진/CS 리포트 라벨 확인, 급여 조회(팀)
payroll.read.team신설(#919), 팀장 기본 역할 ⊇ 일반 직원(#920) 반영 — 커밋 근거 - 카나/PM - 2026-10-07 PR #1057(e240c4d2, MED-915) 반영: 역할 편집 권한 선택을 체크박스 트리 → 리소스 × 동작 범위 매트릭스(없음/본인/팀/전체, 검색·필터·역할 비교)로 전면 교체(40·ㄴ41·ㄴ42) · PR #1055(8f999781·b21b5701·1abffa17, MED-910/911) 반영: 본인/팀/전체 범위 표준화 32행·하위 팀 재귀·기본 거부 게이트·leave/incentive.approve.all 신설 — 커밋 근거, 라이브 실사 이월(TBU) - 카나/PM
- 2026-10-08 (10/7 머지분) PR #1097(d51745b5, MED-955) 반영: 빠진 범위 권한 행 추가(마이그 1960 — 수당·공제 기록/승인, 퇴직·연말정산 기록, 팀원 휴가 기록, 팀 조회(팀), CS 리포트 본인)·매트릭스 「범위 없음」 칸 비활성(ㄴ43)·노트 1행 · PR #1078(12da8faf, MED-946) 반영: 공동 팀장·총괄 팀장(=팀장 묶음 .all)을 「팀장 지정 = 권한 범위 1차 소스」 노트에 이어서 보강 · 40 매트릭스 머리글 원문 — 커밋 근거 + 라이브 실사 확인(2026-10-08, 급여담당 매니저 편집 열람) - 카나/PM
- 2026-10-08 낮 스윕 라이브 실사 — 매트릭스 TBU 일괄 해소: 40 셀 라디오 라벨("없음/본인/팀/전체")·행머리 「모두 전체」·「해제」·상단 컨트롤 원문(검색 placeholder "권한 검색 (리소스·이름·코드)"·「전체 선택/해제」 존치 확인), ㄴ41 카운터 원문 교체("55개 선택 · 총 165개" 형식), ㄴ42 비교 UI("차이만 보기"·셀 "비교: {범위}") 실측, OQ 리소스 총 개수 38종 확정·ward 라벨 재확인 해소 - 카나/PM
- 2026-10-14 (10/13 머지분, #1216 8ebc560 — 프로덕션 배포) 역할 편집 매트릭스 위 「기능별 필수 권한」 번들 줄 신설(35) — 10/14 라이브 실측(그룹·라벨·상태 3종) - 카나/PM
- 2026-10-22 (10/21 머지분) ① #1301(f660c8d) 매트릭스 셀 권한 설명 툴팁 신설(ㄴ44) — 10/22 라이브 실측: 셀 title 툴팁에 범위별 설명(예 「본인 — 본인 교육비 조회: 자신의 교육비 지원 내역만 조회할 수 있습니다 / 팀 — 팀원 교육 조회: …」) ② #1299(b3cfc68) 모든 시스템 역량 권한 행화·#1305 권한 카탈로그 행명 정비(f7cb2e8 연차 설정 행명을 실제 게이트 기준으로 개명 · a1eb089 카탈로그 이름/설명 정합 · 8392bdd 교육/연말정산 승인을 approve 권한으로 게이트 + 마이그레이션 3건 1982~1984) — 매트릭스 행 구성 변동, 전수 재채록은 TBU ③ 권한 매트릭스 묶음 행(스케줄러 관리·연차 설정·설정·권한 미리보기·시트 관리) 10/22 실측. 스샷 live-1022-ad-role-matrix-tooltip.png - 카나/PM
Data I/O
Server → Client
변수
| 메타 | ${roles} |
| 메타 | ${permission_tree} |
| 메타 | ${role_permissions} |
Client → Server
| 액션 | 전달 값 | tRPC procedure | 권한 토큰 |
|---|---|---|---|
| 역할 생성/수정 | 역할명 · 설명 · 상태 · 부서[] · 팀(병동)[] · 권한[] | sdk.role.upsert() (추정) — 부서·팀은 role.create / role.update 의 departmentTeamIds · teamIds | role:write (라벨 "역할 관리", 추정) |
| 역할 삭제 | roleId | sdk.role.delete() (추정) | role:write (추정) |
| 전체 선택/해제 | permission[] 토글 | (클라 트리 조작) |
메인 화면 사양표 (역할 관리)
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | • 조건1 [역할 관리 권한] 보유 시 사이드바 인사 관리 > "역할 관리" 노출. 미보유 시 hide | [[HBAD100_App Shell·사이드바]] | |
| 01 | 초기 상태 | Output | • 역할 카드 목록 표시. 기본 상태 필터 = "활성"(#665, 9/11 — 진입 시 활성 역할만 노출, "전체"로 바꾸면 비활성 포함). 목록 기본 정렬은 실증 불가(라이브 4역할 전부 활성) — TBU | 기본 필터 "활성" | |
| 10 | 역할 카드 목록 | List | • 테넌트 커스텀 역할을 카드로 나열: 역할명 / 설명 / 활성 배지 / 편집 / 삭제 / 펼침. 라이브 카드: 사용자 / 급여담당 매니저 / test / test - CASE01 [활성]: 정상 표기 - CASE02 [비활성]: 카드 회색 처리 | roles | 테넌트 커스텀 |
| 10-E | 목록 Empty | State | • 검색 결과 0건 시 "검색 결과가 없어요" (정책 문구). 라이브 원문 프로브 미확인 | TBU (라이브 확인 필요) | |
| ㄴ11 | 목록 컨트롤 | Button | • 목록 상단 컨트롤: "+ 역할 추가" / 상태 필터(전체/활성/비활성, 기본 "활성" #665) / 부서 필터 / 팀(병동) 필터 / 역할 검색(placeholder "역할") / 페이지네이션 "총 4건 중 1-4건" • "+ 역할 추가" 클릭 시: "역할 추가" 모달(신규) 노출 | 페이지네이션 | |
| ㄴ15 | 부서 필터 | Dropdown | • 역할에 지정한 부서로 목록을 거름. 원문 "전체 부서" / "부서 미지정" / 부서명(이름순) - CASE01 [부서 선택]: 그 부서를 지정한 역할 + 그 부서 아래 팀(병동)만 지정한 역할 - CASE02 [부서 미지정]: 부서도 팀(병동)도 없는 역할 • 변경 시: 팀(병동) 필터를 "전체 팀(병동)"으로 초기화 | roles.departmentTeamIds · roles.teamIds | 클라이언트 필터 |
| ㄴ16 | 팀(병동) 필터 | Dropdown | • 역할에 지정한 팀(병동)으로 목록을 거름. 원문 "전체 팀(병동)" / "팀(병동) 미지정" / 부서별로 묶은 팀명(하위 팀은 "— " 들여쓰기) - CASE01 [팀 선택]: 그 팀 또는 그 아래 하위 팀을 지정한 역할 - CASE02 [팀(병동) 미지정]: 팀(병동)이 없는 역할 - CASE03 [부서 필터 선택됨]: 선택지를 그 부서의 팀으로 좁힘 | roles.teamIds | 클라이언트 필터 |
| ㄴ12 | 편집 | Button | • 카드의 역할 수정 진입 버튼. 원문 "편집" • 클릭 시: "역할 수정" 모달 노출 (기존값 프리필) | roles / role_permissions | |
| ㄴ13 | 삭제 | Button | • 카드의 역할 삭제 버튼(파괴적—기존 기록). 원문 "삭제" • 클릭 시: 컨펌 후 삭제 - CASE01 [일반 역할]: 삭제 가능 - CASE02 [최고 관리자(admin) 역할]: 삭제 버튼 비활성 + 툴팁(정책 "최고 관리자는 삭제할 수 없어요.") - CASE03 [해당 역할 보유 직원 존재]: 정책상 삭제 불가 — 라이브 실차단 문구 프로브 미확인 | roles | admin 차단은 정책·툴팁 TBU |
| ㄴ14 | 펼치기 | Toggle | • 카드 권한 요약을 인라인으로 여닫는 토글, 기본 닫힘. 원문 "펼치기" • 클릭 시: 카드 권한 요약 섹션 펼침(인라인) | role_permissions |
역할 추가·수정 모달 사양표
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | • "+ 역할 추가"(신규) 또는 카드 "편집"(수정) 클릭 시 노출. 모달 제목: 신규 "역할 추가" / 편집 "역할 수정" | 추가/편집 공용 | |
| 10 | 역할명 * | Input | • 역할 이름을 지정하는 필수 항목. 원문 "역할명 *", placeholder "역할" • 입력 시: 값 없음이면 저장 버튼 비활성 | roles.name | 필수 |
| 20 | 설명 | Input | • 역할 설명을 기록하는 선택 항목. 원문 "설명", placeholder "설명" • 입력 시: 설명 기록 | roles.description (추정) | |
| 21 | 부서 | Dropdown | • 역할을 쓰는 부서(팀 관리의 최상위 팀)를 지정하는 선택 항목. 원문 "부서", 첫 항목 "선택 안 함" • ㄴ"중복 부서" 체크박스(드롭다운 아래): - CASE01 [해제·기본]: 하나만 선택 - CASE02 [체크]: 여러 개 선택 — 첫 항목 "부서 추가", 고른 부서는 비활성, 선택 결과는 드롭다운 아래 DS 라벨(누르면 빠짐) - CASE03 [체크 해제]: 먼저 고른 하나만 남음 • 변경 시: 선택한 팀(병동) 중 고른 부서 밖의 팀은 빠짐 | roles.departmentTeamIds | 선택 입력 · 목록 필터용(권한 무관) |
| 22 | 팀(병동) | Dropdown | • 역할을 쓰는 팀(부서 아래 모든 단계의 팀)을 지정하는 선택 항목. 원문 "팀(병동)", 첫 항목 "선택 안 함". 선택지는 부서별 묶음(하위 팀 "— " 들여쓰기), 부서를 골랐으면 그 부서의 팀만 • ㄴ"중복 팀(병동)" 체크박스: 21 과 같은 동작(첫 항목 "팀(병동) 추가") • 라벨 표기: 같은 이름의 팀이 여럿이면 "상위 팀 > 팀명" • 수정 모달: 저장된 값이 2개 이상이면 체크가 켜진 상태로 열림. 체크만 바꾸는 것은 수정 내역이 아님 | roles.teamIds | 선택 입력 · 목록 필터용(권한 무관) |
| 30 | 상태 | Dropdown | • 역할 활성/비활성 상태를 지정, 기본 "활성". 원문 "활성" / "비활성" • 선택 시: 상태 확정. 값 없음: 기본 활성 | roles.isActive | 값 없음: 기본 활성 |
| 35 | 기능별 필수 권한 (번들) | Buttons | • (10/13, #1216 — 프로덕션 배포) 권한 매트릭스 위 버튼 줄 — 기능마다 서버 게이트가 요구하는 최소 권한 묶음(core 상수 FEATURE_PERMISSION_BUNDLES)을 버튼으로 제시, 10/14 실측 그룹·라벨: 직원 앱(직원 앱 기본 · 메신저 · 앱 결재 — 신청 · 앱 결재 — 승인(팀) · 자격증 · 교육(본인) · 급여명세서 · 드라이브 · 공지 · 교육 보기 · 직원 앱 AI 어시스턴트) / 팀장 앱 / 급여 시트(보기 · 편집(전체)) / 관리(직원 관리 · 팀 관리 · 역할 관리 · 총무 관리) • 버튼에 상태 표시 — 충족 / 일부 / 없음(10/14 실측) · 툴팁에 필요한 권한과 모자란 권한 나열 • 클릭 → 모자란 칸만 그 범위로 올림(그 범위 행이 없으면 바로 위 범위) · 이미 더 넓은 칸은 유지(applyBundle) | FEATURE_PERMISSION_BUNDLES · checkBundle/applyBundle(role-permission-matrix, 테스트 포함) | 신설 (#1216) · 라이브 실측 2026-10-14 |
| 40 | 권한 매트릭스 (리소스 × 동작 범위 표) | Grid | • (10/7 전면 교체, #1057, MED-915·MED-910 UI) 권한 148개 체크박스 나열 → 리소스 × 동작 표. 칸마다 범위를 없음/본인/팀/전체 중에서 고름 — 실효 범위는 가장 넓은 것(서버 resolver와 같은 규칙) • 컨트롤: 검색(리소스·이름·코드·설명, 한/영) · 리소스 필터 · 범위 필터 · 「선택된 권한만 보기」 · 선택 개수 표시 · 리소스 단위 모두 전체/해제 • 순수 로직 = role-permission-matrix.ts(테스트 36건). role.listPermissions · role.list(includePermissions)가 conditions(scope)를 돌려줌 • (구) 권한 선택 트리·그룹 카운터·상단 전체 선택 토글은 폐지 | permissions · role_permissions · role.listPermissions | 신설 (e240c4d2, #1057) · 라이브 실사 확인(2026-10-08, 낮 보강): 머리글 원문 "리소스·조회·기록/수정·승인·실행·관리" · 셀 = 라디오 4개 "없음"/"본인"/"팀"/"전체"(리소스×동작별 불가 조합은 비활성) · 행머리 리소스 옆 「모두 전체」·「해제」 버튼 · 상단 컨트롤 원문: 「전체 해제」·「전체 선택」 버튼, 검색 placeholder "권한 검색 (리소스·이름·코드)", 리소스 필터 "전체 리소스"(38종 실측), 범위 필터 "범위 무관"(전체/팀/본인), 체크박스 「선택된 권한만 보기」 — ⚠ 코드 반영분의 "(구) 상단 전체 선택 토글 폐지"와 달리 라이브엔 「전체 선택/해제」 버튼 존치 |
| ㄴ41 | 선택 카운트 | Text | • "{n}개 선택 · 총 {m}개" — 「권한 선택」 섹션 라벨 옆 선택/전체 개수 표기(실시간 갱신, 라이브 예: "55개 선택 · 총 165개") | role_permissions | 라이브 실사 확인(2026-10-08 낮): 원문 교체 — 구 "{n}개 권한 선택됨" 아님 · 총 165개 = 권한 토큰 수 |
| ㄴ42 | 다른 역할과 비교 | Toggle | • 콤보 "다른 역할과 비교"(다른 활성 역할 목록)에서 역할을 골라 두 역할의 권한 차이를 차이 강조로 표시, 「차이만 보기」 필터 제공 — 비교 중 셀에 "비교: 없음"/"비교: 본인"/"비교: 팀"/"비교: 전체" 주석 표기 | role_permissions | 신설 (e240c4d2, #1057) · 라이브 실사 확인(2026-10-08 낮): 콤보·「차이만 보기」·셀 "비교: {범위}" 원문 실측 |
| ㄴ43 | 범위 없는 칸 (비활성) | Rule | • (10/8, #1097, MED-955) 리소스·동작에 그 범위의 권한 행이 없으면 해당 범위 선택지가 비활성 + 툴팁(원문) "이 범위의 권한은 없어요" / 동작 자체에 권한 행이 하나도 없는 칸은 "—" • #1097 이 빠진 행을 채워 아래 범위가 새로 선택 가능: 수당·공제 기록/수정 본인·팀·전체, 승인 팀·전체 / 퇴직·연말정산 기록/수정 본인·팀·전체 / 연차·휴가 기록/수정 팀 / 팀 조회 팀 / CS 리포트 조회·기록/수정 본인 • 의도적으로 「전체」만 두는 칸(비활성 유지): 본인 결재(승인 본인), 관리 칸, 급여 승인·실행·관리, 알림의 팀 범위, 팀·직책·병동·조직 기록 | permissions · locale role.perm_scope_missing | 신설 (d51745b5, #1097) · 라이브 실사 확인(2026-10-08): 수당·공제 기록/수정 없음/본인/팀/전체 선택 가능·승인 본인 ✗(팀·전체 가능), 연말정산 기록/수정 본인/팀/전체, 팀 조회 팀 가능(본인 ✗), 연차/휴가 기록/수정 팀 가능, CS 리포트 행 존재 · 툴팁 원문은 PR 본문 근거(호버 미실사) |
| ㄴ44 | 권한 설명 툴팁 | Tooltip | • (10/21 머지, #1301 f660c8d — 10/22 실측) 매트릭스 셀에 마우스를 올리면 그 칸이 켜는 권한의 범위별 설명 툴팁(title) 표시 — 실측 원문 예(교육 행): "본인 — 본인 교육비 조회: 자신의 교육비 지원 내역만 조회할 수 있습니다 / 팀 — 팀원 교육 조회: 소속 팀원의 교육·교육비 내역을 조회할 수 있습니다 / 전체 — …", 관리 칸 예 "전체 — 교육 관리: 교육 종류 설정과 전체 직원의 교육·교육비 관리 권한" • 설명 원천 = 권한 카탈로그(locales permissions.json) — #1305(a1eb089)가 카탈로그 이름·설명을 실제 게이트와 정합화(연차 설정 행명 f7cb2e8 포함)해 툴팁 문구도 함께 갱신됨 • 공용 Tooltip 컴포넌트(packages/components tooltip.ts) 사용, DS 문서(feedback/tooltip) 갱신 동반 | permissions 카탈로그 · packages/components tooltip | 신설 (#1301) · 10/22 라이브 실측(title 원문 채록) |
| ㄴ45 | 권한 행 구성 변동 (#1299·#1305) | Rule | • (10/21 머지, 커밋 근거) #1299(b3cfc68): 시스템이 게이트하는 모든 역량(대화 복구·대리 접속·조직·저장소·권한 요청·예약 작업 등 34파일 범위)을 권한 행으로 노출 — 매트릭스에서 직접 선택 가능해짐 · #1305: 교육비·연말정산 승인이 approve 권한으로 게이트(8392bdd, 마이그 1984) + 연차 설정 행명을 실제 게이트 기준으로 개명(f7cb2e8, 마이그 1982) + 카탈로그 명칭 정비(a1eb089, 마이그 1983) - 행 전수 재채록(총 행 수·신규 리소스 목록)은 TBU — 묶음 행(스케줄러 관리·연차 설정·설정·권한 미리보기·시트 관리)은 10/22 실측 | permissions · 마이그레이션 1982~1984 | 신설 보고 (#1299·#1305) · TBU: 행 전수 재채록 |
| 50 | admin 역할 편집 제약 | - | • CASE01 [최고 관리자(admin) 역할 수정 모달]: 상태·권한 선택 수정 불가(정책). 역할명·설명은 공통 | roles | 정책 근거, 라이브 프로브 미확인 |
| 60 | 저장 | Button | • 선택 권한으로 역할을 확정하는 버튼. 원문 "저장" • 클릭 시: role_permissions 갱신- CASE01 [성공]: 저장 후 모달 닫힘 - CASE02 [역할명 미입력]: 버튼 비활성 - CASE03 [수정 없음]: 버튼 비활성(편집) | role_permissions | 실패 TBU |
| 70 | 취소 | Button | • 변경 없이 모달을 닫는 버튼. 원문 "취소" • 클릭 시: 모달 닫힘 | ||
| 80 | 이탈 가드 | Dialog | • dirty 상태 이탈 시 노출되는 확정 게이트. 원문 "변경된 내용을 저장하지 않고 나가시겠어요?" (계속 편집 / 나가기) | 7/10 확인 (확정 게이트) |
권한 카탈로그 (리소스 × 액션 × scope) — 라이브 확인
| 리소스 | 액션(scope) | 그룹 카운트 |
|---|---|---|
| 수당 | 관리 / 조회 | 0/2 |
| 공제 | 관리 / 조회 | 0/2 |
| 급여 | 승인 / 계산 / 관리 / 조회 / 조회(본인) / 조회(팀) — payroll.read.team「팀 급여 조회」(#919, 마이그 1933: 팀장 지정 팀 직원 행만 읽기 전용) | (프로브 하단 미노출) |
| 호봉 | 관리 / 조회 | |
| 고정 인센티브 | 관리 / 조회 | 0/2 |
| 인센티브 | 승인(팀) / 조회 / 조회(본인) / 조회(팀) / 수정 / 수정(본인) | |
| 연말정산 | 관리 / 조회 | |
| 근태 | 승인 / 관리 / 조회 / 조회(본인) / 조회(팀) / 수정 / 수정(본인) | 0/7 |
| 초과근무 | 승인(팀) / 관리 / 조회 / 조회(본인) / 조회(팀) / 수정 / 수정(본인) | |
| 외근 | 승인(팀) / 관리 / 조회 / 조회(본인) / 조회(팀) / 수정 / 수정(본인) | |
| 연차/휴가 | 승인(팀) / 조회(본인) / 조회(팀) / 수정(본인) | 0/4 |
| 휴가 신청 | 승인 / 관리 / 조회 / 수정 | |
| 간호 스케줄 | 관리 / 조회 | |
| 스케줄 | 조회(전체/본인/팀) / 수정(전체/본인/팀) | |
| 직원 | 관리 / 조회 / 조회(본인) / 조회(팀) / 수정 / 수정(본인) | 0/6 |
| 부서 | 관리 / 조회 / 수정 | 0/3 |
| 팀 | 관리 / 조회 | |
| 병동 | 관리(ward.manage) / 조회(ward.read) — 라벨 「병동」(#945로 locale 추가, 9/29 이전엔 키 원문 "perm.resource.ward" 노출 버그) | 0/2 |
| 역할 | 관리 / 조회 | |
| 자격증 | 조회(본인) / 수정(본인) | 0/2 |
| 교육 | 조회(본인) / 수정(본인) | 0/2 |
| 교육비 지원 | 관리 / 조회 | 0/2 |
| 문서 | 관리 / 조회 / 조회(본인) / 수정 / 수정(본인) | 0/5 |
| 대화 | 조회 / 수정 | 0/2 |
| 메시지 | 조회 / 수정 | |
| 알림 | 조회 / 조회(본인) / 수정 / 수정(본인) | |
| 총무 | 관리 / 조회 / 수정 | |
| 재고 | 관리 / 조회 | |
| 퇴직 | 관리 / 조회 | |
| 기관 | 조회 / 수정 | |
| 파일 | 조회 / 수정 | |
| 설정 | 수정 | |
| 시스템 | 시스템 관리자 |
기본 역할 팀장(TEAM_LEADER) = 일반 직원 권한 전부 + 팀 범위 권한(시드 47개 = 팀 범위 13 + 본인·조직 공통 34). 기존 조직은 마이그 1935가 누락 17개를 추가(#920, MED-789).
schedule.write.team은 미부여(근무표 편집은nurse-scheduler.manage로 별도 통제).
권한 범위 표준화 (10/7, #1055, MED-910·911): 직원 행이 있는 리소스(근태·휴가·초과근무·외근·인센티브·문서·자격증·교육·수당·공제·퇴사·연말정산)마다 본인/팀/전체 세 범위가 전부 존재하도록 빠진 권한 행 32개를 시드·마이그레이션으로 추가(8f999781 — 1948·1949로 들어갔다가 열린 브랜치와의 충돌로 1952·1953으로 재번호, 1abffa17). 기존 조직의 SUPER_ADMIN·HR_ADMIN에 전부, TEAM_LEADER에 팀 범위 4개(근태 승인·문서·자격증·교육 조회) 부여. 팀 범위 = 소속 팀 + 하위 팀 전체(재귀) — team_members.includeSubTeams(기본 on)가 켜진 소속과 팀장 지정 팀은 하위 팀까지 펼침(utils/team-subtree, resolveResourceScope·loadManagedTeamIds 공통 판정). 서버는 requirePermission을 조직 전체(.all) 전용으로 바꾸고 범위를 거르지 않는 프로시저는 기본 거부(b21b5701, 직원 비귀속 참조 자료·본인 고정 핸들러는 requireAnyScopePermission). 결재 알림 대상도 팀 트리를 받아 상위 팀장이 하위 팀 요청을 받음(MED-911). 전체 휴가 승인
leave.approve.all·전체 인센티브 승인incentive.approve.all신설, HR_ADMIN·SUPER_ADMIN에 부여(820736fa, #1035 계열). 팀장 지정 = 권한 범위 1차 소스 (10/7, MED-945): 소속별 「하위 팀 포함」 토글은 폐기 — 소속·팀장 지정 모두 하위 팀 항상 포함(1955). 팀장 지정은 소속과 독립(어느 팀 소속이든 leaderId 가능, 팀원 자동 추가 없음)이며, leaderId 인 직원은 직책과 무관하게 지정 팀(+하위) 범위에서 팀장 권한 묶음(coreTEAM_LEADER_GRANTS= 기본 「팀장」 역할의 .team 권한: 근태·휴가·초과근무·외근·인센티브 조회·승인, 직원·스케줄·급여·문서·자격증·교육 조회)을 얻는다. 판정 = 역할 권한 ∪ 팀장 묶음(.team), 역할의 .all 우선. 복수 소속은 역할 권한 합집합(가장 넓은 범위).
(10/8, #1078, MED-946) 팀장 지정 보강: 위 노트의 「leaderId 인 직원」은 이제
team_leaders의 팀장 전원(공동 팀장 포함, 읽기 = 표 ∪ 기존 leaderId — 기존 데이터 이관 없음)을 뜻한다.teams.leaderId는 대표 팀장(단톡방 방장)만. 총괄 팀장(team_leaders.teamIdNULL)은 팀장 묶음(TEAM_LEADER_GRANTS)을 조직 전체(.all) 로 얻음 — 팀장 앱 활성 팀 전부 관할·결재 알림 조직 전체 수신(orgLeaderIds). 팀·직책·설정 같은 관리 권한은 여전히 역할이 줌. 지정 화면 = [[HBAD210_팀 관리]] ㄴ30-4.
(10/8, #1097, MED-955) 빠진 범위 행 추가: 매트릭스에서 고를 수 없던 범위를 권한 행으로 채움(마이그레이션 1960):
allowance.write.self/team/all(본인/팀원/전체 수당 기록)·allowance.approve.team/all(팀원/전체 수당 승인)·deduction.write.self/team/all·deduction.approve.team/all·resignation.write.self/team/all(본인/팀원/전체 퇴직 기록)·yearEndSettlement.write.self/team/all(연말정산 기록)·leave.write.team(팀원 휴가 기록)·team.read.team(소속 팀 정보 조회)·csReport.read.self/csReport.write.self(전 역할 backfill). 기존 조직의 SUPER_ADMIN·HR_ADMIN 에 새 행 전부 부여, 커스텀 역할은 자동 매핑 없음(필요 시 매트릭스에서 직접 선택). 권한 행 수: 운영 145 → develop 148 → 마이그 후 165(로컬 실측, PR 본문).
scope 체계
| scope | 범위 | 비고 |
|---|---|---|
| 본인 | 자기 데이터만 | 최하위 |
| 팀 | 소속 팀 범위 | 중간 |
| 전체 | 테넌트 전체 | 최상위 |
권한·상태 분기 요약
| 시나리오 | 트리거 | 결과 화면 | 비고 |
|---|---|---|---|
CASE01 [역할 추가] | "+ 역할 추가" | 역할 추가 모달 (신규) | 권한 "역할 관리" |
CASE02 [권한 저장] | 권한 트리 선택 → 저장 | role_permissions 갱신, "{n}개 권한 선택됨" | |
CASE03 [미저장 이탈] | dirty 후 닫기 | 가드 "변경된 내용을 저장하지 않고 나가시겠어요?" (계속 편집 / 나가기) | 7/10 확인 |
CASE04 [admin 역할] | 삭제/수정 시도 | 삭제 버튼 비활성(툴팁) · 상태/권한 수정 불가 | 정책 근거, 라이브 TBU |
Open Question
- 권한 토큰 내부 key 실제 값 (급여:승인 등 라벨만 확인) = TBU
- 액션 라벨(관리/조회/수정/승인/계산) 최종 상하관계·포함 규칙 = TBU (콸도 미확정)
리소스 총 개수 확정 (약 33 중 census 32건 인용) = TBU→ 해소(2026-10-08 낮 실사): 매트릭스 리소스 필터 38종 실측 (AI 어시스턴트·직원 앱 AI 어시스턴트·수당·연차 촉진·근태·자격증·대화·CS 리포트·공제·부서·문서·교육·교육비 지원·직원·고정 인센티브·총무·인센티브·재고·연차/휴가·휴가 신청·메시지·알림·간호 스케줄·외근·기관·초과근무·급여·퇴직·역할·호봉·스케줄·설정·파일·시스템·팀·드라이브·병동·연말정산) · 권한 토큰 총 165개(ㄴ41 카운터)- 팀 권한(team_permissions) ↔ 역할 권한 병합 우선순위 = TBU
- 역할 저장 실패·역할명 중복 에러 동작 (라이브 프로브 없음) = TBU
- 목록 Empty("검색 결과가 없어요") 라이브 원문 = TBU
ward 리소스 라벨 locale 누락(버그, 9/29 실측)→ 해소(2026-09-29, #945 e23f36e3): ko/en 번들에ward「병동」·aiApp「직원 앱 AI 어시스턴트」·annualLeavePromotion「연차 촉진」·csReport「CS 리포트」 라벨 추가 + 전 리소스·액션 라벨 존재 검사 테스트. 라이브 재확인 완료(2026-10-08 낮 실사): 리소스 필터에 「병동」·「직원 앱 AI 어시스턴트」·「연차 촉진」·「CS 리포트」 한국어 라벨 노출 확인- admin 역할 삭제 툴팁·수정 제약 라이브 확인 = TBU