---
template: policy-doc@1
doc_id: 03-authz-capabilities
title: 능력 — 기업역할 2종 · 쓰기 스코프 · 노출 등급 척도 · 층 순서 · 클라이언트 폴백 비대칭
config: ../_meta/template-config.yaml
last_verified: 4d798f55
policies:
  - id: CORP_SCOPE_VOCABULARY
    status: active-prod
    evidence: [S-contract, S-guard]
    limitations:
      - 두 이름이 같은 축을 부른다는 것까지가 관측이다. 이름이 갈린 것이 의도인지 미완인지는 코드가 말하지 않는다
      - 두 값 밖의 세 번째 등급이 생길 수 있는지는 이 문서가 판정하지 않는다. 지금 대입되는 자리가 둘이라는 사실까지다
    anchors:
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:114
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:132
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:169
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:192
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.dto.ts:83
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:155
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21
  - id: ORG_WRITE_SCOPE
    status: active-prod
    evidence: [S-guard, S-route]
    limitations:
      - 예외 표식이 붙은 처리기가 내부에서 실제로 범위를 다시 검증하는지는 이 문서가 세지 않는다. 표식의 자리까지가 사정거리다
      - 미결선 표면의 손판정이 이 가드와 같은 판정을 하는지는 문면 대조까지이며 동치 증명이 아니다
    anchors:
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:24
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:33
      - insuniverse-server/apps/api/src/modules/auth/admin/allow-org-write.decorator.ts:6
      - insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:53
      - insuniverse-server/apps/api/src/modules/user/user-admin.controller.ts:21
  - id: ORG_WRITE_FLAG
    status: active-prod
    evidence: [S-contract, S-component]
    limitations:
      - 고정값 대입이 의도인지 미완인지는 코드가 말하지 않는다. 대입 자리와 그 귀결까지가 관측이다
      - 이 플래그를 뒤집는 운영 설정이 저장소 밖에 있는지는 판정하지 않는다
    anchors:
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:164
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.dto.ts:95
      - insuniverse-admin/src/api/authApi.ts:76
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:20
  - id: CORP_ANALYSIS_VIEW_SCALE
    status: active-prod
    evidence: [S-schema, S-guard]
    limitations:
      - 척도의 범위를 적는 자리가 어디인가까지다. 기업별로 무엇이 배정돼 있는지는 이 문서 부록이 따로 다룬다
      - 세 단계라는 것은 주석 두 자리가 적는 것이고 코드가 강제하지 않는다. 열에 범위 제약이 없고 비교가 크기 비교라 척도 밖 값이 저장돼도 이 층은 막지 않는다
      - 데코레이터 인자 형은 처리기가 요구할 수 있는 값만 닫는다. 배정값 쪽 범위는 닫지 않는다
    anchors:
      - insuniverse-server/drizzle/schema.ts:404
      - insuniverse-server/drizzle/schema.ts:405
      - insuniverse-server/apps/api/src/modules/auth/admin/auth.dto.ts:99
      - insuniverse-server/apps/api/src/modules/agency/agency/agency.entity.ts:56
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:16
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:20
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:34
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:40
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:47
      - insuniverse-server/apps/api/src/modules/analyze/analyze-admin.controller.ts:45
      - insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:46
  - id: LAYER_PRECEDENCE
    status: active-prod
    evidence: [S-guard, S-route]
    limitations:
      - 순서가 선언 순서로 정해진다는 것까지가 관측이다. 그 순서가 의도된 설계인지는 코드가 말하지 않는다
      - 부분집합 결선이 그 표면에서 옳은 선택인지는 이 문서가 판정하지 않는다
    anchors:
      - insuniverse-server/apps/api/src/modules/analyze/analyze-admin.controller.ts:43
      - insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:36
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:27
      - insuniverse-server/apps/api/src/modules/money/money-admin.controller.ts:70
  - id: CLIENT_GATE_ASYMMETRY
    status: active-prod
    evidence: [S-component, S-guard]
    limitations:
      - 두 폴백 방향이 반대라는 것까지가 관측이다. 어느 쪽이 옳은지는 이 문서가 판정하지 않는다
      - 화면이 접는 것은 편집 UI 이고 요청 자체를 막지는 않는다. 그 우회 경로의 전수는 세지 않았다
    anchors:
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:19
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:20
      - insuniverse-admin/src/features/authority/lib/corpRole.ts:21
      - insuniverse-admin/src/api/authApi.ts:74
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21
  - id: CORP_ANALYSIS_VIEW_ASSIGNMENT
    status: data-dependent-unknown
    evidence: [S-schema, A-comment]
    unknown_reason: 기업별 배정값이 운영 DB 열에 있고 저장소에는 그 열의 선언과 조회 자리만 있다. 어느 기업에 어떤 값이 실려 있는지 이 저장소에서 판정되지 않는다
    limitations:
      - 배정값의 소재와 척도 범위까지가 이 정책의 사정거리다. 실제 값은 인용하지 않는다
    anchors:
      - insuniverse-server/drizzle/schema.ts:405
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:20
      - insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:45
      - insuniverse-admin/src/pages/Admin/Corp/Corp/DetailCorpPage.tsx:266
---

# 능력 — 기업역할 2종 · 쓰기 스코프 · 노출 등급 척도 · 층 순서 · 클라이언트 폴백 비대칭

이 문서는 **계정 종류가 같은 주체 안에서 다시 갈리는 차단**을 정한다. 기업 측 관리자가 두 등급으로 갈리고, 한쪽은 쓰기가 기본 차단되며, 분석 화면 접근은 기업별 노출 등급으로 다시 갈린다는 것이 이 문서의 핵심이다.

**여기는 3층과 4층만 쓴다.** `../_meta/template-config.yaml` `auth_layers` 의 `쓰기 스코프`와 `기업 노출 등급`이며 둘 다 차단 응답은 403 이다. 계정 종류로 갈리는 2층은 `./02-authz-roles.md` 소관이고, 사이드바 노출만 정하고 API 를 막지 않는 메뉴 노출층은 `./04-authz-db-menu.md` 소관이다. 이 문서는 그 둘을 대신 서술하지 않는다.

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

**기업별 배정값은 본문에 없다.** 노출 등급의 **척도**를 적는 자리는 저장소에 있고 판정되지만, 어느 기업에 무엇이 배정돼 있는가는 운영 데이터라 이 저장소로 판정되지 않는다. 그래서 그 축만 `## 부록` 으로 격리했다. 배치의 정본은 `../_meta/template-config.yaml` 의 `statuses` 다.

## 정책 (기획)

### CORP_SCOPE_VOCABULARY

**기업 측 관리자는 두 등급으로 갈린다.** 전사 범위를 갖는 최고관리자와 자기 조직 부분트리로 스코프되는 조직관리자 둘이며, 두 등급은 서로 다른 로그인 입구로 들어온다.

**같은 축을 두 이름이 부른다.** 로그인 응답 본문이 쓰는 필드 이름과 발급되는 토큰이 싣는 필드 이름이 다르고, 두 이름이 취하는 값의 표기도 다르다. **화면은 응답 본문 쪽 이름을 읽고 서버 판정은 토큰 쪽 이름을 읽는다.**

**그래서 "기업역할" 이라는 말만으로는 어느 이름을 가리키는지 정해지지 않는다.** 두 이름은 같은 사실을 말하지만 서로를 참조하지 않으며, 한쪽을 고쳐도 다른 쪽이 따라오지 않는다.

### ORG_WRITE_SCOPE

**조직 범위 주체의 쓰기는 기본 차단이다.** 조회 요청은 항상 통과하고, 조회가 아닌 요청은 **명시적 예외 표식**이 붙은 처리기에서만 통과한다. 전사 범위 주체와 기업 밖 주체는 이 층의 대상이 아니다.

**이 층도 표면마다 개별로 결선된다.** 그래서 기업 측 관리자가 닿을 수 있는 표면 중 이 층을 결선하지 않은 것이 남아 있다.

**미결선 표면 중 일부는 같은 판정을 처리기 안에서 손으로 한다.** 조직 범위인지 확인하고 그 자리에서 거부하거나 조회 조건을 좁히는 분기가 컨트롤러 본문에 있다. 그 분기가 이 층과 **같은 판정인지는 이 문서가 증명하지 않는다** — 문면이 같은 값을 본다는 것까지가 관측이다.

**예외 표식이 하는 일은 통과시키는 것뿐이다.** 표식이 붙은 처리기가 자기 범위를 다시 검증하는지는 그 처리기 몫이며 이 층이 보증하지 않는다.

### ORG_WRITE_FLAG

**조직 범위 주체의 운영 가능 여부를 나르는 플래그가 따로 있다.** 로그인 응답과 토큰이 함께 싣고, 관리자 콘솔 화면이 그 값을 읽어 편집 UI 를 켜고 끈다.

**그러나 그 값은 로그인 시점에 고정값으로 대입된다.** 조건에 따라 달라지는 자리가 저장소에 없고, 조직 범위로 로그인한 모든 주체가 같은 값을 받는다.

**그래서 저장소 기준으로 이 플래그는 분기를 만들지 않는다.** 화면 쪽에는 이 값이 없을 때를 위한 폴백이 있으나, 지금 발급되는 모든 세션에서 그 폴백은 발동하지 않는다. 이 문서는 그 고정이 의도인지 미완인지 판정하지 않는다.

### CORP_ANALYSIS_VIEW_SCALE

**분석 화면 접근은 기업별 노출 등급으로 갈린다.** 등급은 순서가 있는 값이며 — 미노출 · 목록까지 · 상세까지 — 처리기가 요구하는 단계보다 기업의 배정 등급이 낮으면 차단된다. 판정은 크기 비교다.

**척도를 적는 자리는 넷이다.** 등급을 담는 열의 머리 주석 · 판정 층의 머리 주석 · 로그인 응답 계약의 설명문 · 기업 엔티티 계약의 설명문이 같은 세 단계를 같은 순서로 적는다. **넷 중 어느 것도 값을 제약하지 않는다** — 앞 둘은 실행되지 않는 주석이고 뒤 둘은 문서 생성용 문자열이다. 열에는 범위 제약이 없고 판정이 크기 비교라, 척도 밖의 값이 저장돼도 이 층은 막지 않고 요구 단계 이상이면 통과시킨다.

**형이 닫는 것은 요구 쪽뿐이다.** 처리기가 요구 단계를 지정할 때 받는 값의 형은 두 값으로 닫혀 있어 **요구할 수 있는 단계**는 그 둘로 한정된다. 배정값 쪽 범위는 그 형이 닫지 않는다. 열 기본값 선언은 새 기업의 시작 등급을 정할 뿐 취할 수 있는 값을 정하지 않는다.

**판정은 토큰이 아니라 저장소를 다시 조회해서 한다.** 설정 변경이 즉시 반영되게 하려는 선택이며, 그래서 세션이 살아 있는 동안 등급이 바뀌면 그다음 요청부터 새 등급으로 판정된다.

**대상은 기업 측 관리자뿐이다.** 다른 계정 종류는 이 층을 통과하며, 요구 단계가 지정되지 않은 처리기도 통과한다.

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

### LAYER_PRECEDENCE

**층의 적용 순서는 표면이 선언한 목록의 순서가 정한다.** 목록에 실린 차례대로 판정되고, 앞선 층에서 막히면 뒤의 층은 실행되지 않는다.

**그 순서는 `../_meta/template-config.yaml` 의 `auth_layers` 와 같다.** 저장소에서 두 개 이상의 층을 함께 선언한 목록 전건이 그 순서의 부분수열이며, 순서를 거스른 목록은 없다.

**부분집합 결선이 허용된다.** 표면은 자기에게 필요한 층만 골라 실을 수 있고, 실제로 대부분의 표면이 4층을 전부 걸지 않는다. **그래서 어떤 표면은 2·3층을 건너뛰고 4층만 건다** — 그 표면에서는 계정 종류와 쓰기 스코프가 이 층 계열에서 판정되지 않는다.

**앞 층을 건너뛴다고 뒤 층이 약해지지는 않는다.** 각 층은 자기 조건만 보며 서로의 결과를 참조하지 않는다.

### CLIENT_GATE_ASYMMETRY

**판정 불가한 기업 주체에 대해 화면과 서버가 반대 방향으로 폴백한다.**

관리자 콘솔 화면은 **조회전용으로 접는다.** 전사 범위임이 확인되지 않고 운영 가능 플래그도 참이 아니면, 안전한 쪽을 골라 편집 UI 를 닫는다.

서버의 쓰기 스코프 층은 **통과시킨다.** 조직 범위임이 확인되지 않으면 이 층의 대상이 아니라고 보고 아무것도 하지 않는다.

**두 폴백은 같은 입력에서 반대 결론을 낸다.** 화면이 닫은 편집을 서버는 막지 않으므로, 화면을 거치지 않고 요청을 보내면 그 요청은 이 층에서 차단되지 않는다. 이 문서는 어느 쪽이 옳은지 판정하지 않는다 — 방향이 반대라는 사실까지가 관측이다.

## 강제 지점 (개발)

### CORP_SCOPE_VOCABULARY

- **기업역할 값** — `CORP_SUPER` · `CORP_ORG`
- **토큰 payload 필드** — `insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:114` · `insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:169`
- **응답 본문 필드** — `insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:132` · `insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:192`
- **응답 본문 필드의 계약 선언** — `insuniverse-server/apps/api/src/modules/auth/admin/auth.dto.ts:83`
- **토큰 필드를 읽는 서버 판정** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21`

### ORG_WRITE_SCOPE

- **조직 범위 판정** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21`
- **조회 통과** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:24`
- **차단 지점** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:33`
- **예외 표식 선언** — `insuniverse-server/apps/api/src/modules/auth/admin/allow-org-write.decorator.ts:6`
- **예외 표식** — `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:263` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:276` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:346` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:381` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:416` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:429` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:444` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:457` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:481` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:502` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:518` · `insuniverse-server/apps/api/src/modules/money/money-admin.controller.ts:288` · `insuniverse-server/apps/api/src/modules/money/money-admin.controller.ts:298` · `insuniverse-server/apps/api/src/modules/money/money-admin.controller.ts:331` · `insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:132`
- **가드 결선** — `insuniverse-server/apps/api/src/modules/agency/settlement/settlement-admin.controller.ts:41` · `insuniverse-server/apps/api/src/modules/analyze/analyze-admin.controller.ts:43` · `insuniverse-server/apps/api/src/modules/fc/agency/agency-fc-admin.controller.ts:53` · `insuniverse-server/apps/api/src/modules/money/money-admin.controller.ts:70` · `insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:36` · `insuniverse-server/apps/api/src/modules/order/order/order-admin.controller.ts:33` · `insuniverse-server/apps/api/src/modules/subscribe/subscribe/subscribe-admin.controller.ts:29`
- **미결선 표면** — `insuniverse-server/apps/api/src/modules/agency/agency/agency-admin.controller.ts:29` · `insuniverse-server/apps/api/src/modules/agency/agency/corp-my.controller.ts:29` · `insuniverse-server/apps/api/src/modules/agency/organization/organization-admin.controller.ts:42` · `insuniverse-server/apps/api/src/modules/agency/organization/organization-corp.controller.ts:31` · `insuniverse-server/apps/api/src/modules/user/user-admin.controller.ts:21`
- **미결선 표면의 손판정 예** — `insuniverse-server/apps/api/src/modules/agency/agency/corp-my.controller.ts:37` · `insuniverse-server/apps/api/src/modules/agency/organization/organization-admin.controller.ts:53` · `insuniverse-server/apps/api/src/modules/user/user-admin.controller.ts:44`

### ORG_WRITE_FLAG

- **고정값 대입** — `insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:164`
- **계약 선언** — `insuniverse-server/apps/api/src/modules/auth/admin/auth.dto.ts:95`
- **화면 쪽 형 선언** — `insuniverse-admin/src/api/authApi.ts:76`
- **화면 쪽 소비** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:20`

### CORP_ANALYSIS_VIEW_SCALE

- **척도 열거 자리** — `insuniverse-server/drizzle/schema.ts:404` · `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:20` · `insuniverse-server/apps/api/src/modules/auth/admin/auth.dto.ts:99` · `insuniverse-server/apps/api/src/modules/agency/agency/agency.entity.ts:56`
- **열 기본값** — 범위 제약이 아니라 새 기업의 시작 등급이다. `insuniverse-server/drizzle/schema.ts:405`
- **요구 단계 형** — 요구 쪽만 닫는다. `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:16`
- **통과 분기** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:34` · `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:40`
- **데코레이터 사용** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:29` · `insuniverse-server/apps/api/src/modules/analyze/analyze-admin.controller.ts:45` · `insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:46` · `insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:104`
- **가드 결선** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:27` · `insuniverse-server/apps/api/src/modules/analyze/analyze-admin.controller.ts:43` · `insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:36`
- **차단 비교** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:47`

### LAYER_PRECEDENCE

- **전체 결선** — `insuniverse-server/apps/api/src/modules/analyze/analyze-admin.controller.ts:43` · `insuniverse-server/apps/api/src/modules/order/order-detail/order-detail-admin.controller.ts:36`
- **부분집합 결선** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:27` · `insuniverse-server/apps/api/src/modules/money/money-admin.controller.ts:70`

### CLIENT_GATE_ASYMMETRY

- **화면 쪽 전사 범위 확인** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:19`
- **화면 쪽 운영 가능 확인** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:20`
- **화면 쪽 보수 폴백** — `insuniverse-admin/src/features/authority/lib/corpRole.ts:21`
- **화면이 읽는 필드의 형** — `insuniverse-admin/src/api/authApi.ts:74`
- **서버 쪽 관대 폴백** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21`

### CORP_ANALYSIS_VIEW_ASSIGNMENT

- **배정값이 사는 열** — `insuniverse-server/drizzle/schema.ts:405`
- **척도 범위를 적은 주석** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:20`
- **배정값 조회** — `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:45`
- **배정값 설정 화면** — `insuniverse-admin/src/pages/Admin/Corp/Corp/DetailCorpPage.tsx:266`

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

| 정책 id | server | site | admin |
|---|---|---|---|
| CORP_SCOPE_VOCABULARY | 두 입구의 값 대입 · 계약 선언 | — | 응답 본문 필드 소비 |
| ORG_WRITE_SCOPE | 가드 판정 · 예외 표식 · 표면별 결선 | — | — |
| ORG_WRITE_FLAG | 고정값 대입 · 계약 선언 | — | 형 선언 · 편집 UI 분기 |
| CORP_ANALYSIS_VIEW_SCALE | 열 기본값 · 요구 단계 지정 · 가드 판정 | — | 등급 값을 읽는 화면 게이팅 |
| LAYER_PRECEDENCE | 표면별 선언 목록 순서 | — | — |
| CLIENT_GATE_ASYMMETRY | 관대 폴백 | — | 보수 폴백 · 형 선언 |
| CORP_ANALYSIS_VIEW_ASSIGNMENT | 열 선언 · 조회 | — | 설정 화면 |

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

이 표의 열은 서비스 3종이며 actor 는 열이 아니다. 이 문서의 축인 기업역할 등급은 actor 축의 한 원소 안에서 갈리는 것이라 열로 두면 다섯 원소 중 하나만 채워진 표가 된다. 열 이름 집합과 순서는 `../_meta/template-config.yaml` 의 `services` 를 그대로 따르며 계획서 게이트 `#13` 이 그 대조를 돌린다.

## 예외·폴백

| 정책 id | 예외 조건 | 폴백 동작 | 확인 근거 |
|---|---|---|---|
| CORP_SCOPE_VOCABULARY | 응답 본문 쪽 이름으로 서버 판정을 찾으려 할 때 | 찾지 못한다. 서버는 토큰 쪽 이름을 읽는다 | `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21` |
| CORP_SCOPE_VOCABULARY | 조직 범위 로그인인데 소속 조직이 배정돼 있지 않을 때 | 스코프를 정의할 수 없어 로그인 자체가 거부된다 | `insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:155` |
| ORG_WRITE_SCOPE | 조직 범위 주체의 조회 요청일 때 | 항상 통과한다 | `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:24` |
| ORG_WRITE_SCOPE | 주체가 조직 범위가 아닐 때 | 이 층이 아무것도 하지 않는다. 전사 범위 · 다른 계정 종류 · 미인증이 전부 여기로 온다 | `insuniverse-server/apps/api/src/modules/auth/admin/corp-readonly.guard.ts:21` |
| ORG_WRITE_SCOPE | 표면이 이 층을 결선하지 않았을 때 | 쓰기 스코프가 판정되지 않는다. 일부 표면은 같은 판정을 처리기 안에서 손으로 한다 | `insuniverse-server/apps/api/src/modules/agency/organization/organization-admin.controller.ts:53` |
| ORG_WRITE_FLAG | 이 플래그가 없는 세션일 때 | 화면이 조회전용으로 접는다. 다만 지금 발급되는 조직 범위 세션은 전부 값을 싣는다 | `insuniverse-server/apps/api/src/modules/auth/admin/auth.service.ts:164` |
| CORP_ANALYSIS_VIEW_SCALE | 처리기가 요구 단계를 지정하지 않았을 때 | 이 층이 통과시킨다 | `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:40` |
| CORP_ANALYSIS_VIEW_SCALE | 기업 측 관리자가 아닐 때 | 이 층이 통과시킨다 | `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:34` |
| CORP_ANALYSIS_VIEW_SCALE | 배정 등급이 척도 밖의 값일 때 | 이 층이 막지 않는다. 비교가 크기 비교라 요구 단계 이상이면 통과한다 | `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:47` |
| LAYER_PRECEDENCE | 표면이 일부 층만 선언했을 때 | 선언하지 않은 층은 그 표면에서 실행되지 않는다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:27` |
| LAYER_PRECEDENCE | 앞선 층에서 차단됐을 때 | 뒤의 층은 실행되지 않는다 | `insuniverse-server/apps/api/src/modules/analyze/analyze-admin.controller.ts:43` |
| CLIENT_GATE_ASYMMETRY | 기업 주체인데 등급도 운영 가능 여부도 확인되지 않을 때 | 화면은 접고 서버는 통과시킨다. 방향이 반대다 | `insuniverse-admin/src/features/authority/lib/corpRole.ts:21` |
| CORP_ANALYSIS_VIEW_ASSIGNMENT | 어느 기업에 어떤 등급이 배정돼 있는지 저장소에서 확인하려 할 때 | 확인되지 않는다. 값을 지어내지 않고 미상으로 둔다. 부록 참조 | `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:45` |

## 부록

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

### CORP_ANALYSIS_VIEW_ASSIGNMENT

**기업별 노출 등급은 운영 저장소의 한 열에 산다.** 저장소에 있는 것은 그 열의 선언과, 판정 시점에 그 열을 다시 읽는 자리와, 그 값을 편집하는 관리자 콘솔 화면뿐이다.

**그래서 "이 기업은 상세까지 볼 수 있다" 를 이 문서가 말할 수 없다.** 척도를 적는 자리는 본문이 열었고, 어느 기업이 그중 무엇인지는 여기서 판정되지 않는다. 이 절은 소재와 범위만 열고 실제 값을 인용하지 않는다. **적힌 척도 밖의 값이 실려 있을 가능성도 배제되지 않는다** — 열에 범위 제약이 없어 저장소가 그것을 막지 않는다.

**열의 기본값은 코드에 있다.** 새로 만들어진 기업이 어떤 등급으로 시작하는지까지는 저장소가 말한다 — 그 뒤 운영에서 무엇으로 바뀌었는지가 판정되지 않는 부분이다.

- 근거 자리 — `insuniverse-server/drizzle/schema.ts:405` · `insuniverse-server/apps/api/src/modules/auth/admin/corp-analysis-view.guard.ts:45` · `insuniverse-admin/src/pages/Admin/Corp/Corp/DetailCorpPage.tsx:266`

## 연혁

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

| 릴리스 | 날짜 | SHA | 변경 요약 |
|---|---|---|---|
| — | 2026-01-19 | `cc8feb03` | 기업 측 관리자 로그인 신설 — 이 문서의 축이 생긴 시점 |
| — | 2026-07-01 | `f0ce46c8` | 조직관리자 입구 · 부분트리 스코프 · 쓰기 기본 차단 층 · 예외 표식이 한 커밋에 도입됨 |
| — | 2026-07-01 | `55c4eaac` | 관리자 열람 단명토큰 신설 — 2·3층을 건너뛰고 4층만 거는 표면이 생김 |
| — | 2026-07-06 | `397f7453` | 기업 청구·머니 축에 쓰기 스코프 층이 결선됨 |
| — | 2026-07-24 | `54473012` | 기업별 분석관리 노출 등급 열과 그 게이팅 층이 도입됨 |
| — | 2026-07-31 | `299d60bc` | 기업 측 관리자의 자동차분석 열람 허용 — 노출 등급 축의 적용 표면이 늘어남 |
