---
template: policy-doc@1
doc_id: 04-authz-db-menu
title: 메뉴 노출 — 비차단 층 · actor 3분기 트리 · 기업 별도 네임스페이스 · 권한그룹 배분 미상
config: ../_meta/template-config.yaml
last_verified: 4d798f55
policies:
  - id: MENU_LAYER_NONBLOCKING
    status: active-prod
    evidence: [S-route, S-guard]
    limitations:
      - 메뉴 조회 처리기 둘에 계정 종류 층이 결선돼 있지 않다는 것까지가 관측이다. 그 상태가 의도인지 미완인지는 코드가 말하지 않는다
      - 브라우저 안의 경로 판정은 화면을 돌려세울 뿐이며, 그 판정을 거치지 않고 보낸 요청이 어디까지 닿는지의 전수는 이 문서가 세지 않았다
    anchors:
      - insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:15
      - insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:25
      - insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:26
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:32
      - insuniverse-admin/src/layouts/AdminLayout.tsx:85
      - insuniverse-admin/src/layouts/AdminLayout.tsx:323
      - insuniverse-admin/src/layouts/AdminLayout.tsx:328
  - id: ADMIN_MENU_TREE
    status: active-prod
    evidence: [S-schema, S-route]
    limitations:
      - 운영 저장소에 실제로 어떤 항목이 등록돼 있는지는 이 저장소가 말하지 않는다. 트리를 만드는 조회 경로와 조립 규칙까지가 사정거리다
      - 상위 항목이 함께 딸려 오는 규칙은 한 단계 위만 본다. 조부모 이상이 어떻게 되는지는 이 조회가 정하지 않는다
    anchors:
      - insuniverse-server/drizzle/schema.ts:1570
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:36
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:37
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:38
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:41
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:49
      - insuniverse-server/apps/api/src/modules/menu/menu.service.ts:41
      - insuniverse-admin/src/layouts/AdminLayout.tsx:242
      - insuniverse-admin/src/features/login/hooks/useLoginForm.ts:111
  - id: SALES_MENU_TREE
    status: active-prod
    evidence: [S-constant, S-component]
    limitations:
      - 필터를 통과하지 못하는 트리 항목이 왜 트리에 남아 있는지는 코드가 말하지 않는다. 남아 있다는 것과 사이드바에 나타나지 않는다는 것까지가 관측이다
      - 같은 코드가 두 자리에 적힌 것이 의도인지 실수인지도 이 문서가 판정하지 않는다
    anchors:
      - insuniverse-admin/src/features/authority/constants/menu.ts:7
      - insuniverse-admin/src/features/authority/constants/menu.ts:174
      - insuniverse-admin/src/layouts/AdminLayout.tsx:44
      - insuniverse-admin/src/layouts/AdminLayout.tsx:256
      - insuniverse-admin/src/features/login/hooks/useLoginForm.ts:114
  - id: CORP_MENU_TREE
    status: active-prod
    evidence: [S-constant, S-component]
    limitations:
      - 게이팅이 읽는 두 값의 정의와 척도는 이 문서가 쓰지 않는다. 읽는다는 사실과 그 자리까지가 사정거리이며 축은 인접 문서 소관이다
      - 숨김 목록에 대상이 없는 원소가 섞여 있다는 관측은 발견 기록에 있고, 그 원소가 왜 거기 있는지는 이 문서가 판정하지 않는다
    anchors:
      - insuniverse-admin/src/features/authority/constants/menu.ts:190
      - insuniverse-admin/src/features/authority/constants/menu.ts:269
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:43
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:75
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:77
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:78
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:81
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:86
      - insuniverse-admin/src/layouts/AdminLayout.tsx:266
      - insuniverse-admin/src/layouts/AdminLayout.tsx:271
      - insuniverse-admin/src/features/login/hooks/useLoginForm.ts:118
      - insuniverse-admin/src/features/login/hooks/useLoginForm.ts:121
  - id: ADMIN_MENU_ASSIGNMENT
    status: data-dependent-unknown
    evidence: [S-schema, A-comment]
    unknown_reason: 권한그룹에 어떤 메뉴가 배분돼 있는지는 운영 저장소의 매핑 표 행에 있고, 이 저장소에는 그 표의 선언과 조회 자리와 배분을 편집하는 화면만 있다. 어느 그룹에 무엇이 배분돼 있는지 이 저장소로 판정되지 않는다
    limitations:
      - 배분의 소재와 조회 경로까지가 이 정책의 사정거리다. 실제 배분 값을 인용하지 않으며 어떤 계수도 적지 않는다
      - 이 저장소의 이관 스크립트는 증분만 담고 최초 적재분을 담지 않는다. 그래서 이 저장소만으로는 배분은커녕 항목 전수도 재구성되지 않는다
    anchors:
      - insuniverse-server/drizzle/schema.ts:1588
      - insuniverse-server/drizzle/schema.ts:1589
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:30
      - insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:37
      - insuniverse-admin/src/pages/Admin/Security/Authority/DetailAuthorityPage.tsx:35
---

# 메뉴 노출 — 비차단 층 · actor 3분기 트리 · 기업 별도 네임스페이스 · 권한그룹 배분 미상

이 문서는 **사이드바에 무엇이 보이는가**를 정한다. 보이는 항목의 집합이 로그인 주체마다 어떻게 정해지는지, 그 집합이 어디서 오는지가 이 문서의 축이다.

**여기는 5층 하나만 쓴다.** `../_meta/template-config.yaml` `auth_layers` 의 `메뉴 노출` 이며, 그 층은 **차단 층이 아니다.** 인증되지 않은 요청을 되돌리는 1층은 `./01-authn.md` 소관이고, 계정 종류로 갈라 403 을 내는 2층은 `./02-authz-roles.md` 소관이며, 같은 계정 종류 안에서 다시 갈리는 3·4층은 `./03-authz-capabilities.md` 소관이다. 층 축 밖의 개별 열람 토큰은 `./05-admin-view-token.md` 소관이다. 이 문서는 그 넷을 대신 서술하지 않는다.

**`## 정책 (기획)` 절에는 코드 심볼을 쓰지 않는다.** 예외는 각 정책의 `### <id>` 제목뿐이며, 상수 이름·표 이름·화면 이름·함수 이름은 전부 `## 강제 지점 (개발)` 소관이다.

**수치를 이 문서가 적지 않는다.** 프론트 상수로 확정되는 축의 전수와 계수는 추출 규약 동결본이 싣고 커밋된 추출기가 재현한다 — 이 문서는 그 자리를 강제 지점 절에서 가리킬 뿐 값을 옮겨 적지 않는다. 운영 저장소에서 오는 축은 그 동결본이 전수 미확보를 선언했으므로 **어떤 수도 적지 않는다.**

**로그인 주체 3종이 본문에 나란히 선다.** 관리자 · 영업대리점 · 기업담당자 순이며, 각 절의 첫 문단이 트리 소스 · 코드 체계 · 확정 여부 셋을 먼저 적는다. 그중 관리자 축만 정책이 둘로 갈린다 — 트리를 만드는 구조와 조회 경로는 코드가 말하므로 본문이고, 권한그룹에 무엇이 배분됐는가만 운영 데이터라 `## 부록` 이 소재만 연다. 배치의 정본은 `../_meta/template-config.yaml` 의 `statuses` 다.

## 정책 (기획)

### MENU_LAYER_NONBLOCKING

**메뉴 노출은 서버 응답을 막지 않는다.** 이 층이 정하는 것은 사이드바에 무엇을 그릴지와 로그인 직후 어느 화면으로 보낼지 둘뿐이다.

**메뉴가 보이지 않는 주체도 주소를 직접 치면 응답을 받는다.** 그 요청이 막히는지는 계정 종류 층과 개별 판정이 정하며, 메뉴 집합은 그 판정에 입력으로 들어가지 않는다.

**메뉴를 내주는 두 조회는 계정 종류로 갈리지 않는다.** 하나는 로그인한 관리자에게 자기 몫의 트리를 내주고 다른 하나는 전체 트리를 내주는데, 전자는 인증만 요구하고 **후자는 그것마저 요구하지 않는다.** 두 조회 어디에도 계정 종류 판정이 걸려 있지 않다.

**브라우저 안에서는 메뉴 집합이 경로 접근도 함께 정한다.** 관리자 콘솔은 지금 열려는 경로가 자기 메뉴 집합에 있는지 보고, 없으면 권한 없음 화면으로 돌려세운다. **그 판정은 브라우저에 있다** — 화면을 거치지 않고 보낸 요청은 그 판정을 통과하지 않으며, 서버는 이 층을 다시 확인하지 않는다.

**그래서 메뉴 권한을 인가로 읽으면 틀린다.** 이 문서가 서술하는 집합은 화면에 무엇이 보이는가이지 무엇이 허용되는가가 아니다.

### ADMIN_MENU_TREE

**관리자의 트리 소스는 운영 저장소다.** 코드 체계는 운영 저장소의 메뉴 표가 쓰는 것이며, 트리 구조와 조회 경로는 이 저장소에서 확정된다. 로그인 주체 셋 중 **운영 저장소를 런타임에 조회하는 것은 관리자뿐이다.**

**자기 몫의 트리는 권한그룹을 매개로 만들어진다.** 메뉴 표와 배분 표와 관리자 표 셋을 이어 붙여 그 관리자가 속한 권한그룹에 배분된 항목을 고른다.

**배분된 항목의 상위 항목이 배분 없이도 함께 딸려 온다.** 그래서 **그룹 머리가 보인다는 것이 그 아래 전부가 배분됐다는 뜻이 아니다** — 하위 하나만 배분돼도 머리는 보인다.

**배분이 하나도 없으면 트리가 빈 채로 끝난다.** 그 경우 조회는 그 자리에서 되돌아오고 상위 승계도 일어나지 않는다.

**평평한 목록이 상하 관계로 조립된다.** 상위가 그 목록 안에 없는 항목은 최상위로 올라가고, 있으면 그 아래로 붙는다.

**로그인 직후 진입 화면이 이 트리에서 정해진다.** 지정된 첫 화면에 대한 배분이 있으면 거기로 가고, 없으면 자기 트리에서 처음 닿을 수 있는 화면으로 간다. 그마저 없으면 권한 없음 화면으로 간다. **셋 중 어디로 가는지가 배분에 따라 달라지는 것이 이 축의 성질이다.**

**어느 그룹에 무엇이 배분돼 있는지는 여기 없다.** 그 축은 운영 데이터라 이 저장소로 판정되지 않으며 `## 부록` 이 소재만 연다.

### SALES_MENU_TREE

**영업대리점의 트리 소스는 브라우저 안 상수다.** 코드 체계는 관리자 축과 **같은 체계**를 쓰고, 트리와 필터가 둘 다 코드에 있어 **확정된다.** 이 주체는 운영 저장소의 트리를 **조회하지 않는다.**

**두 상수가 대조되어 실효 집합이 나온다.** 하나는 화면 구조를 담은 트리이고 다른 하나는 통과시킬 코드의 목록이다. 대조는 브라우저에서 일어나고 서버는 관여하지 않는다.

**코드가 붙지 않은 항목은 상위의 판정을 따른다.** 그래서 코드 없는 그룹 머리는 그 아래가 통과할 때 함께 남는다.

**트리에 있으나 필터를 통과하지 못하는 항목이 있다.** 그 항목들은 **사이드바에 절대 나타나지 않는다.** 그리고 같은 코드가 트리의 두 자리에 적혀 있다. 트리에 적힌 코드의 출현 수와 실효 집합의 크기가 다른 이유가 그 둘이다.

**로그인 직후 진입 화면은 고정이다.** 트리를 보지 않고 정해진 한 곳으로 간다.

### CORP_MENU_TREE

**기업담당자의 트리 소스도 브라우저 안 상수다.** 다만 코드 체계가 **다르다** — 관리자 축의 체계와 겹치지 않는 별도 접두를 쓴다. 트리와 필터가 둘 다 코드에 있어 **확정되며**, 이 주체도 운영 저장소의 트리를 **조회하지 않는다.**

**두 체계를 한 사전에서 찾으면 어긋난다.** 기업 축의 코드는 운영 저장소의 메뉴 표에 없고, 반대로 그 표의 코드는 기업 축의 상수에 없다.

**통과시킬 코드의 목록이 그대로 쓰이지 않고 한 번 줄어든다.** 줄이는 판정이 두 갈래다. 하나는 기업 안에서 이 담당자가 어떤 등급인가를 보고 최고 등급 전속 항목을 걷어내며, 다른 하나는 이 기업에 분석 화면을 어디까지 열어 두었는가를 보고 그 항목 하나를 걷어낸다.

**그 두 값이 무엇인지는 이 문서가 쓰지 않는다.** 둘 다 같은 계정 종류 안에서 다시 갈리는 축이며 `./03-authz-capabilities.md` 가 정의와 척도를 갖는다. 여기서는 **읽는다는 사실과 그 자리**까지만 적는다.

**등급이 확인되지 않으면 줄이는 쪽으로 간다.** 최고 등급임이 확인될 때만 전속 항목이 남고, 그 밖은 전부 걷어내는 쪽으로 떨어진다.

**걷어낼 코드 목록에 대상이 없는 원소가 섞여 있다.** 트리에도 필터에도 없는 코드가 그 목록에 있으며, 그 원소는 아무것도 걷어내지 않는다. 이 관측은 `../_meta/findings/20-foundation-access.md` 에 기록돼 있다.

**로그인 직후 진입 화면은 고정이되 등급에 따라 두 곳으로 갈린다.** 트리를 보지 않고 등급만 보고 정해진다.

## 강제 지점 (개발)

### MENU_LAYER_NONBLOCKING

- **메뉴 조회 처리기** — `insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:15` · `insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:25`
- **결선된 층** — 인증 하나뿐이며 계정 종류 층은 어느 쪽에도 없다. `insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:26`
- **무결선 처리기** — `insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:15`
- **반환만 하는 조회** — `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:32`
- **브라우저 안 경로 판정** — `insuniverse-admin/src/layouts/AdminLayout.tsx:85` · `insuniverse-admin/src/layouts/AdminLayout.tsx:323`
- **브라우저 안 되돌림** — `insuniverse-admin/src/layouts/AdminLayout.tsx:328`

### ADMIN_MENU_TREE

- **메뉴 표 선언** — `insuniverse-server/drizzle/schema.ts:1570`
- **조인 3테이블** — `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:36` · `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:37` · `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:38`
- **빈 배분 조기반환** — `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:41`
- **상위 승계** — `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:49`
- **트리 조립** — `insuniverse-server/apps/api/src/modules/menu/menu.service.ts:41`
- **트리 소스 분기** — `insuniverse-admin/src/layouts/AdminLayout.tsx:242`
- **로그인 직후 진입** — `insuniverse-admin/src/features/login/hooks/useLoginForm.ts:111`

### SALES_MENU_TREE

- **트리 상수** — `insuniverse-admin/src/features/authority/constants/menu.ts:7`
- **필터 배열** — `insuniverse-admin/src/features/authority/constants/menu.ts:174`
- **필터 함수 선언** — `insuniverse-admin/src/layouts/AdminLayout.tsx:44`
- **트리 소스 분기** — `insuniverse-admin/src/layouts/AdminLayout.tsx:256`
- **로그인 직후 진입** — `insuniverse-admin/src/features/login/hooks/useLoginForm.ts:114`
- **하드코딩 축 전수와 계수** — 이 문서가 적지 않는다. `../_meta/extraction-manifest.yaml` `menu_codes.hardcoded` 가 전수·계수·집합 해시를 싣고 `../_meta/verify/extract-menu-codes.mjs` 가 재현한다

### CORP_MENU_TREE

- **트리 상수** — `insuniverse-admin/src/features/authority/constants/menu.ts:190`
- **필터 배열** — `insuniverse-admin/src/features/authority/constants/menu.ts:269`
- **숨김 목록** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:43`
- **게이팅 함수** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:75`
- **게이팅 입력** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:77` · `insuniverse-admin/src/features/authority/lib/corpRole.ts:78`
- **게이팅 분기** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:81` · `insuniverse-admin/src/features/authority/lib/corpRole.ts:86`
- **트리 소스 분기** — `insuniverse-admin/src/layouts/AdminLayout.tsx:266` · `insuniverse-admin/src/layouts/AdminLayout.tsx:271`
- **로그인 직후 진입** — `insuniverse-admin/src/features/login/hooks/useLoginForm.ts:118` · `insuniverse-admin/src/features/login/hooks/useLoginForm.ts:121`
- **층 위임** — 게이팅 입력 둘의 정의와 척도는 `./03-authz-capabilities.md` 가 갖는다. 이 문서는 자리만 연다

### ADMIN_MENU_ASSIGNMENT

- **배분이 사는 표** — `insuniverse-server/drizzle/schema.ts:1588`
- **권한그룹 열** — `insuniverse-server/drizzle/schema.ts:1589`
- **배분 규약 주석** — `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:30`
- **배분 조회 경로** — `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:37`
- **배분 설정 화면** — `insuniverse-admin/src/pages/Admin/Security/Authority/DetailAuthorityPage.tsx:35`

## 적용 범위 (actor × 서비스)

| 정책 id | server | site | admin |
|---|---|---|---|
| MENU_LAYER_NONBLOCKING | 메뉴 조회 처리기 둘 · 결선 층 | — | 브라우저 안 경로 판정 · 되돌림 |
| ADMIN_MENU_TREE | 조인 조회 · 상위 승계 · 트리 조립 | — | 런타임 조회 · 로그인 직후 진입 |
| SALES_MENU_TREE | — | — | 트리 상수 · 필터 배열 · 브라우저 대조 · 고정 진입 |
| CORP_MENU_TREE | — | — | 트리 상수 · 필터 배열 · 게이팅 · 고정 진입 2분기 |
| ADMIN_MENU_ASSIGNMENT | 매핑 표 선언 · 조회 | — | 배분 설정 화면 |

`—` = 그 서비스가 이 정책의 경로에 등장하지 않음.

이 표의 열은 서비스 3종이며 actor 는 열이 아니다. 이 문서의 축인 로그인 주체 3분기는 정책 id 로 이미 갈려 있어 열로 다시 두면 각 행에 한 칸만 차는 표가 된다. 열 이름 집합과 순서는 `../_meta/template-config.yaml` 의 `services` 를 그대로 따르며 이 마일스톤 계획서 게이트 `#17` 이 그 대조를 돌린다.

## 예외·폴백

| 정책 id | 예외 조건 | 폴백 동작 | 확인 근거 |
|---|---|---|---|
| MENU_LAYER_NONBLOCKING | 사이드바에 없는 경로로 요청을 직접 보낼 때 | 이 층이 막지 않는다. 차단 여부는 계정 종류 층과 개별 판정이 정한다 | `insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:26` |
| MENU_LAYER_NONBLOCKING | 전체 트리 조회를 인증 없이 부를 때 | 이 층도 인증 층도 막지 않는다. 그 처리기에는 어떤 층도 결선돼 있지 않다 | `insuniverse-server/apps/api/src/modules/menu/menu.controller.ts:15` |
| MENU_LAYER_NONBLOCKING | 관리자 콘솔에서 메뉴 집합 밖 경로를 열려 할 때 | 브라우저가 권한 없음 화면으로 돌려세운다. 서버 판정은 아니다 | `insuniverse-admin/src/layouts/AdminLayout.tsx:328` |
| ADMIN_MENU_TREE | 그 관리자에게 배분된 항목이 하나도 없을 때 | 트리가 빈 채로 끝난다. 상위 승계도 일어나지 않는다 | `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:41` |
| ADMIN_MENU_TREE | 하위 하나만 배분되고 그 상위는 배분되지 않았을 때 | 상위가 함께 딸려 온다. 상위가 보인다는 것이 그 아래 전부가 배분됐다는 뜻이 아니다 | `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:49` |
| ADMIN_MENU_TREE | 지정된 첫 화면에 대한 배분이 없을 때 | 자기 트리에서 처음 닿을 수 있는 화면으로 가고, 그마저 없으면 권한 없음 화면으로 간다 | `insuniverse-admin/src/features/login/hooks/useLoginForm.ts:111` |
| SALES_MENU_TREE | 트리 항목에 코드가 붙어 있지 않을 때 | 상위의 판정을 그대로 따른다 | `insuniverse-admin/src/layouts/AdminLayout.tsx:44` |
| SALES_MENU_TREE | 트리에 있으나 필터를 통과하지 못하는 항목일 때 | 사이드바에 절대 나타나지 않는다 | `insuniverse-admin/src/features/authority/constants/menu.ts:174` |
| CORP_MENU_TREE | 기업 안 등급이 확인되지 않을 때 | 최고 등급 전속 항목을 걷어내는 쪽으로 떨어진다 | `insuniverse-admin/src/features/authority/lib/corpRole.ts:86` |
| CORP_MENU_TREE | 이 기업에 분석 화면을 열어 둔 정도가 없거나 최저일 때 | 그 항목 하나를 목록에서 걷어낸다 | `insuniverse-admin/src/features/authority/lib/corpRole.ts:81` |
| CORP_MENU_TREE | 걷어낼 코드 목록의 원소가 트리에도 필터에도 없을 때 | 아무것도 걷어내지 않는다. 그 원소는 대상 없이 남아 있다 | `insuniverse-admin/src/features/authority/lib/corpRole.ts:43` |
| ADMIN_MENU_ASSIGNMENT | 어느 권한그룹에 어떤 항목이 배분돼 있는지 저장소에서 확인하려 할 때 | 확인되지 않는다. 값을 지어내지 않고 미상으로 둔다. 부록 참조 | `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:37` |

## 부록

이 절의 정책은 **활성 여부가 운영 데이터에 걸려 있어 현행을 판정하지 못한다.** 매핑 표의 선언과 조회 자리와 편집 화면은 코드가 말하지만 그 표에 실린 행은 운영 저장소에 있다. 그 상태로 본문에 두면 독자가 확정된 배분으로 읽는다. 배치의 정본은 `../_meta/template-config.yaml` 의 `statuses` 이며, 값이 확인되면 상태가 바뀌고 배치도 함께 옮긴다.

### ADMIN_MENU_ASSIGNMENT

**권한그룹에 대한 메뉴 배분은 운영 저장소의 매핑 표에 산다.** 저장소에 있는 것은 그 표의 선언과, 트리를 만들 때 그 표를 거쳐 가는 조회와, 배분을 편집하는 관리자 콘솔 화면뿐이다.

**그래서 "이 그룹은 여기까지 본다" 를 이 문서가 말할 수 없다.** 트리를 만드는 규칙은 본문이 열었고, 어느 그룹이 무엇을 받았는지는 여기서 판정되지 않는다. 이 절은 소재와 조회 경로만 열고 **실제 배분 값을 인용하지 않으며 어떤 계수도 적지 않는다.**

**이 저장소의 이관 스크립트로는 재구성되지 않는다.** 증분만 담겨 있고 최초 적재분이 없어, 배분은 물론 항목 전수도 이 저장소에서 복원되지 않는다.

**본문의 관리자 절과 이 절은 같은 축의 두 부분이다.** 조회 경로와 조립 규칙은 판정됐고 그 경로가 읽는 데이터만 판정되지 않았다. 그래서 정책을 둘로 갈랐다 — 하나로 두면 판정된 구조까지 이 절로 끌려온다.

- 근거 자리 — `insuniverse-server/drizzle/schema.ts:1588` · `insuniverse-server/apps/api/src/modules/menu/menu.repository.ts:37` · `insuniverse-admin/src/pages/Admin/Security/Authority/DetailAuthorityPage.tsx:35`

## 연혁

릴리스 태그가 존재하지 않는다. 릴리스 열은 `—` 로 두고 커밋 SHA 로 추적한다.

| 릴리스 | 날짜 | SHA | 변경 요약 |
|---|---|---|---|
| — | 2025-04-03 | `afdbf4df` | 권한그룹·메뉴 배분 축이 서버에 처음 들어옴 |
| — | 2026-01-15 | `27f2f6b5` | 관리자 사이드바가 상수에서 운영 저장소 조회로 옮겨감 |
| — | 2026-01-19 | `b8ed533e` | 기업담당자 로그인 신설 — 별도 네임스페이스 상수 트리가 생긴 시점 |
| — | 2026-07-01 | `c8419274` | 기업 축 메뉴가 4그룹으로 재편되고 등급 전속 항목 숨김 목록이 도입됨 |
| — | 2026-07-13 | `97202a0c` | 운영 핫픽스로 기업 축 트리가 축소됨 |
| — | 2026-07-24 | `c4f96eea` | 기업별 분석 화면 노출 정도가 메뉴 게이팅 입력으로 추가됨 |
| — | 2026-07-31 | `daa7bef6` | 기업 축에 주문·정산 항목이 다시 노출됨 |
| — | 2026-07-31 | `b753586b` | 기업 조직관리 화면 신설 — 등급별 고정 진입 2분기가 생긴 시점 |
