---
template: policy-doc@1
doc_id: 05-admin-view-token
title: 관리자 열람 단명토큰 — 발급 조건 · 대상 결박 · 전달 두 경로 · 신원 복원 · 서명키 · 강제 게이트 미상
config: ../_meta/template-config.yaml
last_verified: 4d798f55
policies:
  - id: VIEW_TOKEN_ISSUE
    status: active-prod
    evidence: [S-guard, S-route]
    limitations:
      - 발급 입구에 결선된 층이 무엇인가까지가 관측이다. 그 층들이 이 표면에서 옳은 선택인지는 이 문서가 판정하지 않는다
      - 기업 측 주체의 대상 소유 확인은 조회 한 건으로 판정된다. 그 조회가 소유의 정의를 옳게 옮겼는지는 이 문서가 증명하지 않는다
    anchors:
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:19
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:27
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:29
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:36
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:42
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:46
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:59
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:63
  - id: VIEW_TOKEN_BINDING
    status: active-prod
    evidence: [S-guard, S-constant]
    limitations:
      - 대상 3필드가 함께 서명되고 함께 대조된다는 것까지가 관측이다. 서명 방식 자체의 강도는 이 문서가 평가하지 않는다
      - 만료 기본값이 사는 자리는 열되 값은 적지 않는다. 운영에서 그 자리가 어떤 값으로 덮여 있는지는 이 저장소가 말하지 않는다
    anchors:
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:24
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:36
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:70
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:76
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:77
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:79
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:109
  - id: VIEW_TOKEN_DELIVERY
    status: active-prod
    evidence: [S-component, S-route]
    limitations:
      - 전달 경로가 둘이라는 것과 각 경로의 자리까지가 관측이다. 두 경로가 동시에 실렸을 때의 우선순위는 검증 쪽 자리가 정하며 이 문서는 그 자리만 연다
      - 헤더가 붙는 경로 접두 목록에 열람 화면이 함께 쓰는 공용 조회가 포함된다. 그 포함이 필요한 범위인지는 이 문서가 판정하지 않는다
    anchors:
      - insuniverse-admin/src/pages/Admin/Subscription/Analysis/IframeAnalysisPopup.tsx:33
      - insuniverse-admin/src/pages/Admin/Subscription/Analysis/IframeAnalysisPopup.tsx:83
      - insuniverse-admin/src/pages/Corp/Subscription/Analysis/IframeAnalysisPopup.tsx:33
      - insuniverse-site/front/src/shared/api/index.ts:53
      - insuniverse-site/front/src/shared/api/index.ts:55
      - insuniverse-site/front/src/shared/api/index.ts:76
      - insuniverse-site/front/src/shared/api/index.ts:86
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:29
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:30
      - insuniverse-server/apps/api/src/modules/analyze/analyze-admin-view.controller.ts:36
      - insuniverse-server/apps/api/src/modules/b2c/analyze/b2c-analyze-admin-view.controller.ts:38
      - insuniverse-server/apps/api/src/modules/client/analyze/client-analyze-admin-view.controller.ts:36
  - id: VIEW_TOKEN_IDENTITY
    status: active-prod
    evidence: [S-guard, S-test]
    limitations:
      - 구판 토큰이 신원을 복원하지 않는다는 것까지가 관측이다. 구판이 아직 발급되는 자리가 있는지는 이 문서가 세지 않았다
      - 비차단 복원 경로에서 차단을 정하는 것은 그 뒤의 소유자 검증이다. 그 검증의 전수는 이 문서 범위 밖이다
    anchors:
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:37
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:38
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:105
      - insuniverse-server/apps/api/src/modules/auth/admin/car-view-admin.guard.ts:21
      - insuniverse-server/apps/api/src/modules/auth/admin/admin-optional.guard.ts:46
      - insuniverse-server/apps/api/src/modules/auth/admin/admin-optional.guard.ts:63
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.spec.ts:40
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.spec.ts:53
  - id: VIEW_TOKEN_SECRET
    status: active-prod
    evidence: [S-guard, A-comment]
    limitations:
      - 두 키의 우선순위와 둘 다 없을 때의 귀결까지가 관측이다. 운영에서 어느 쪽이 실려 있는지는 이 저장소가 말하지 않는다
      - 키 부재가 닫히는 쪽으로 떨어진다는 것은 검증 경로에 한정된다. 발급 경로는 키 부재에서도 값을 만들어 낸다
    anchors:
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:21
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:22
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:23
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:56
  - id: VIEW_TOKEN_ENFORCE_GATE
    status: conditional-unknown
    evidence: [S-guard, A-comment]
    unknown_reason: 차단 여부가 실행 환경의 게이트 값 하나에 걸려 있고 그 값을 운영에서 무엇으로 두었는지 이 저장소에 없다. 값을 정하는 자리가 저장소에 0건이라 켜졌는지 꺼졌는지 판정되지 않는다
    limitations:
      - 게이트가 꺼진 동안의 동작과 켜진 뒤의 동작 둘 다 코드가 말한다. 지금 어느 쪽인지만 판정되지 않는다
      - 이 게이트는 검증 결선 경로에만 걸린다. 비차단 복원 경로는 이 게이트와 무관하게 요청을 막지 않는다
    anchors:
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:46
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:49
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:51
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:54
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:57
---

# 관리자 열람 단명토큰 — 발급 조건 · 대상 결박 · 전달 두 경로 · 신원 복원 · 서명키 · 강제 게이트 미상

이 문서는 **관리자가 회원 화면을 그대로 들여다보는 통로**를 정한다. 그 통로는 다른 출처의 화면 안에서 열리기 때문에 로그인 세션이 함께 실리지 않고, 그래서 세션 대신 건마다 발급되는 단명 값이 인가를 나른다.

**여기는 층 축 밖이다.** `../_meta/template-config.yaml` `auth_layers` 의 5층 중 어느 것도 이 문서의 축이 아니다. 이것은 특정 표면 묶음에만 걸리는 개별 판정이며, 같은 계정 종류 안에서 다시 갈리는 3·4층은 `./03-authz-capabilities.md` 소관이고 사이드바에 무엇이 보이는가를 정하는 5층은 `./04-authz-db-menu.md` 소관이다. 이 문서는 그 둘을 대신 서술하지 않는다.

**이 문서가 답하는 질문은 하나다.** 식별자가 순차 정수인데 **번호만 바꿔 가며 남의 건을 열 수 있는가.** 답은 아래 대상 결박 정책이 낸다.

**`## 정책 (기획)` 절에는 코드 심볼을 쓰지 않는다.** 예외는 각 정책의 `### <id>` 제목뿐이며, 가드 이름·헤더 이름·질의 인자 이름·환경 설정 키는 전부 `## 강제 지점 (개발)` 소관이다.

**값이 아니라 자리를 연다.** 서명 방식의 재현 절차 · 서명키 · 만료 기본값 · 게이트 설정 키의 이름은 이 문서에 적지 않는다. 강제 지점 절이 여는 것은 그 판정이 사는 **자리**이며, 거기까지가 이 문서의 사정거리다.

**강제 여부만 부록이다.** 발급 · 결박 · 전달 · 신원 복원 · 서명키 다섯은 코드가 말하므로 본문이고, 미검증 요청을 실제로 막고 있는가만 실행 환경의 게이트에 걸려 있어 `## 부록` 으로 격리했다. 배치의 정본은 `../_meta/template-config.yaml` 의 `statuses` 다.

## 정책 (기획)

### VIEW_TOKEN_ISSUE

**발급은 관리자 인증을 통과한 요청에만 열린다.** 이 입구는 관리자 콘솔의 세션으로 부르며, 세션이 없으면 값을 얻지 못한다.

**요청할 수 있는 대상 종류는 세 값으로 닫혀 있다.** 목록 밖의 종류를 요청하면 거부되고, 식별자가 양의 정수가 아니어도 거부된다.

**기업 측 주체에는 두 가지가 더 걸린다.** 하나는 그 기업에 분석 상세를 열어 둔 정도가 요구 단계에 미치는가이고, 다른 하나는 **요청한 건이 자기 기업 범위 안의 것인가**이다. 후자는 발급 시점에 저장소를 다시 조회해서 판정한다.

**조직 범위로 스코프된 주체는 그 부분트리 안으로 더 좁혀진다.** 같은 기업 안이어도 자기 조직 밖의 건이면 발급되지 않는다.

**기업 측 주체가 요청할 수 있는 대상 종류는 셋 중 하나뿐이다.** 나머지 둘은 종류 자체로 거부된다.

### VIEW_TOKEN_BINDING

**발급된 값은 대상 1건과 만료 시각에 결박된다.** 대상 종류 · 대상 식별자 · 만료 시각 셋이 서명 안에 함께 들어가고, 검증이 그 셋을 요청이 가리키는 대상과 다시 대조한다.

**그래서 식별자만 순차로 바꿔서는 다른 건에 닿지 못한다.** 번호를 바꾸면 서명이 덮은 식별자와 요청의 식별자가 어긋나 검증이 실패하고, 서명을 다시 만들려면 서명키가 필요하다. **이것이 이 문서가 답하는 질문에 대한 답이다.**

**서명 비교는 길이를 먼저 보고 그다음 내용을 상수 시간으로 본다.** 비교에 걸리는 시간에서 정답에 얼마나 가까운지가 새어 나가지 않게 하는 선택이다.

**만료는 기본값이 코드에 있고 그 자리가 실행 환경 값으로 열려 있다.** 값 자체는 이 문서가 적지 않는다.

**만료된 값은 검증을 통과하지 못한다.** 만료 시각이 서명 안에 있으므로 그 시각을 늘려 잡는 것도 서명 없이는 되지 않는다.

### VIEW_TOKEN_DELIVERY

**전달 경로가 둘이다.** 관리자 콘솔이 발급받아 열람 화면 주소의 질의 인자로 실어 보내고, 열람 화면이 그 값을 **페이지가 뜰 때 한 번 잡아 두었다가** 이후 호출에 헤더로 붙인다.

**한 번만 잡는 것이 요건이다.** 열람 화면 안에서 화면을 옮겨 다니면 주소가 바뀌는데, 처음 잡아 둔 값을 계속 쓰기 때문에 그때마다 다시 발급받지 않아도 된다.

**헤더가 붙는 대상은 경로 접두 목록으로 제한된다.** 열람 화면 자신의 조회뿐 아니라 **그 화면이 함께 쓰는 공용 조회**도 그 목록에 있다. 그 공용 조회는 회원 화면도 쓰는 자리이며, 관리자가 세션 없이 그 자리를 부를 때 이 값이 인가를 대신 나른다.

**받는 쪽은 두 경로를 모두 본다.** 질의 인자와 헤더 중 어느 쪽으로 와도 같은 검증을 거친다.

**검증을 결선한 열람 표면은 셋이다.** 세 종류의 분석 상세가 각각 자기 대상 종류로 검증한다.

### VIEW_TOKEN_IDENTITY

**완전 검증된 현행 판만 관리자 신원을 복원한다.** 복원되는 것은 넷이다 — 계정 종류 · 관리자 식별자 · 자동차 분석을 열람할 수 있는가를 나르는 값, 그리고 이 통로로 들어왔다는 표시다.

**구판 값은 신원을 복원하지 않는다.** 구판은 일반 열람만 통과시키고 신원 자리를 비워 두므로, 그 뒤에 신원을 요구하는 판정은 **닫히는 쪽으로 떨어진다.** 구판 호환은 폐기 문서로 승계하지 않고 이 문서의 예외 행으로 적는다.

**신원 복원에는 비차단 경로도 있다.** 회원 화면과 관리자 열람이 함께 쓰는 공개 조회에서 관리자 신원을 복원하되, 값이 없거나 무효여도 요청 자체를 막지 않는다. **차단 여부는 그 뒤의 소유자 검증이 정한다.**

**회원 쪽 인증 값으로는 관리자로 오인되지 않는다.** 회원 값에는 계정 종류 자리가 없고 판정이 그 자리를 보기 때문이다.

### VIEW_TOKEN_SECRET

**서명키는 전용 값이 우선이고 없으면 다른 키를 재사용한다.** 두 자리를 순서대로 보고 먼저 있는 것을 쓴다.

**둘 다 없으면 빈 키가 된다.** 그 상태에서 검증은 값을 보기도 전에 되돌아오므로 **전건 실패한다.** 키 부재의 폴백 방향이 닫히는 쪽이라는 것이 이 정책의 요점이다.

**발급 쪽은 키가 없어도 값을 만들어 낸다.** 그렇게 만들어진 값은 검증을 통과하지 못하므로, 키 부재는 발급 실패가 아니라 열람 실패로 나타난다.

## 강제 지점 (개발)

### VIEW_TOKEN_ISSUE

- **발급 처리기** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:36`
- **결선된 층** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:27`
- **대상 종류 화이트리스트** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:19`
- **대상 종류 거부** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:42`
- **식별자 형 거부** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:46`
- **기업 주체 추가 판정** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:29` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:63`
- **기업 주체 종류 제한** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:59`

### VIEW_TOKEN_BINDING

- **서명 대상 조립** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:36`
- **서명** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:109`
- **상수시간 비교** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:70`
- **대상 3필드 대조** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:76` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:77` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:79`
- **만료 기본값 자리** — 값은 적지 않는다. `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:24`

### VIEW_TOKEN_DELIVERY

- **질의 인자 적재** — `insuniverse-admin/src/pages/Admin/Subscription/Analysis/IframeAnalysisPopup.tsx:33` · `insuniverse-admin/src/pages/Corp/Subscription/Analysis/IframeAnalysisPopup.tsx:33`
- **발급 호출** — `insuniverse-admin/src/pages/Admin/Subscription/Analysis/IframeAnalysisPopup.tsx:83`
- **최초 1회 캡처** — `insuniverse-site/front/src/shared/api/index.ts:53` · `insuniverse-site/front/src/shared/api/index.ts:55`
- **부착 대상 접두 목록** — `insuniverse-site/front/src/shared/api/index.ts:76`
- **헤더 부착** — `insuniverse-site/front/src/shared/api/index.ts:86`
- **수신 자리** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:29` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:30`
- **검증 결선 처리기** — `insuniverse-server/apps/api/src/modules/analyze/analyze-admin-view.controller.ts:36` · `insuniverse-server/apps/api/src/modules/b2c/analyze/b2c-analyze-admin-view.controller.ts:38` · `insuniverse-server/apps/api/src/modules/client/analyze/client-analyze-admin-view.controller.ts:36`

### VIEW_TOKEN_IDENTITY

- **신원 복원 조건** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:37`
- **복원되는 값** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:38`
- **구판 판정** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:105`
- **닫히는 쪽 판정** — `insuniverse-server/apps/api/src/modules/auth/admin/car-view-admin.guard.ts:21`
- **비차단 복원** — `insuniverse-server/apps/api/src/modules/auth/admin/admin-optional.guard.ts:46` · `insuniverse-server/apps/api/src/modules/auth/admin/admin-optional.guard.ts:63`
- **회귀 시험** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.spec.ts:40` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.spec.ts:53`

### VIEW_TOKEN_SECRET

- **키 우선순위** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:22` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:23`
- **키 부재 주석** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:21`
- **빈 키 조기 반환** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:56`

### VIEW_TOKEN_ENFORCE_GATE

- **게이트 주석** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:46`
- **게이트 판정** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:49`
- **경고 기록** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:51`
- **미검증 통과 분기** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:54`
- **차단 분기** — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:57`

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

| 정책 id | server | site | admin |
|---|---|---|---|
| VIEW_TOKEN_ISSUE | 발급 처리기 · 결선 층 · 종류·식별자 거부 · 기업 추가 판정 | — | 발급 호출 |
| VIEW_TOKEN_BINDING | 서명 조립 · 서명 · 상수시간 비교 · 3필드 대조 | — | — |
| VIEW_TOKEN_DELIVERY | 수신 자리 · 검증 결선 처리기 셋 | 최초 1회 캡처 · 접두 목록 · 헤더 부착 | 질의 인자 적재 |
| VIEW_TOKEN_IDENTITY | 복원 조건 · 구판 판정 · 비차단 복원 · 회귀 시험 | — | — |
| VIEW_TOKEN_SECRET | 키 우선순위 · 빈 키 조기 반환 | — | — |
| VIEW_TOKEN_ENFORCE_GATE | 게이트 판정 · 통과 분기 · 차단 분기 | — | — |

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

이 표의 열은 서비스 3종이며 actor 는 열이 아니다. 이 문서의 축은 특정 표면 묶음에 걸리는 개별 판정이라 actor 를 열로 두면 관리자 한 칸만 차는 표가 된다. 열 이름 집합과 순서는 `../_meta/template-config.yaml` 의 `services` 를 그대로 따르며 이 마일스톤 계획서 게이트 `#17` 이 그 대조를 돌린다.

## 예외·폴백

| 정책 id | 예외 조건 | 폴백 동작 | 확인 근거 |
|---|---|---|---|
| VIEW_TOKEN_ISSUE | 대상 종류가 세 값 밖일 때 | 발급 전에 거부된다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:42` |
| VIEW_TOKEN_ISSUE | 식별자가 양의 정수가 아닐 때 | 발급 전에 거부된다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:46` |
| VIEW_TOKEN_ISSUE | 기업 측 주체가 자기 범위 밖의 건을 요청할 때 | 발급되지 않는다. 조직 범위 주체는 그 부분트리 밖도 같다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:63` |
| VIEW_TOKEN_ISSUE | 기업 측 주체가 나머지 두 종류를 요청할 때 | 종류 자체로 거부된다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.controller.ts:59` |
| VIEW_TOKEN_BINDING | 식별자만 바꿔 다른 건을 열려 할 때 | 서명이 덮은 식별자와 어긋나 검증이 실패한다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:77` |
| VIEW_TOKEN_BINDING | 만료 시각이 지난 값일 때 | 검증이 실패한다. 만료도 서명이 덮으므로 늘려 잡을 수 없다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:79` |
| VIEW_TOKEN_DELIVERY | 열람 화면 안에서 화면을 옮겨 주소가 바뀔 때 | 처음 잡아 둔 값을 계속 쓴다. 다시 발급받지 않는다 | `insuniverse-site/front/src/shared/api/index.ts:53` |
| VIEW_TOKEN_DELIVERY | 호출 경로가 접두 목록 밖일 때 | 헤더를 붙이지 않는다 | `insuniverse-site/front/src/shared/api/index.ts:76` |
| VIEW_TOKEN_IDENTITY | 구판 값으로 열람할 때 | 신원이 복원되지 않아 그 뒤의 판정이 닫히는 쪽으로 떨어진다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:105` |
| VIEW_TOKEN_IDENTITY | 공용 조회에 값이 없거나 무효일 때 | 요청 자체는 막지 않는다. 차단 여부는 그 뒤 소유자 검증이 정한다 | `insuniverse-server/apps/api/src/modules/auth/admin/admin-optional.guard.ts:63` |
| VIEW_TOKEN_SECRET | 전용 키가 없을 때 | 다른 키를 재사용한다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:23` |
| VIEW_TOKEN_SECRET | 두 키가 다 없을 때 | 검증이 전건 실패한다. 닫히는 쪽 폴백이다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:56` |
| VIEW_TOKEN_ENFORCE_GATE | 강제 게이트가 켜져 있지 않을 때 | 미검증 요청도 통과한다. 경고 기록만 남는다 | `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:54` |

## 부록

이 절의 정책은 **활성 여부가 실행 환경의 설정에 걸려 있어 현행을 판정하지 못한다.** 켜졌을 때의 동작과 꺼졌을 때의 동작은 둘 다 코드가 말하지만, 지금 어느 쪽인가를 정하는 값이 이 저장소에 없다. 그 상태로 본문에 두면 독자가 차단이 기본이라고 읽는다. 배치의 정본은 `../_meta/template-config.yaml` 의 `statuses` 이며, 값이 확인되면 상태가 바뀌고 배치도 함께 옮긴다.

### VIEW_TOKEN_ENFORCE_GATE

**차단은 게이트 하나에 걸려 있다.** 그 게이트가 켜져 있을 때만 검증에 실패한 요청이 거부되고, 켜져 있지 않으면 **미검증 요청도 그대로 통과하며 경고 기록만 남는다.**

**무중단 전개를 위한 순서다.** 코드를 먼저 배포해도 기존 열람 화면이 깨지지 않게 해 두고, 발급과 전달이 실제로 이루어지는지 운영에서 확인한 뒤 켠다는 것이 그 자리의 주석이 적는 의도다.

**그 게이트의 운영 값이 이 저장소에 없다.** 값을 정하는 자리가 저장소에 하나도 없어 켜졌는지 꺼졌는지 판정되지 않는다. **값을 추정하지 않는다** — 지금 IDOR 차단이 실제로 발동하고 있는가에 이 문서는 답하지 않는다.

**게이트와 무관한 부분은 본문에 있다.** 발급 조건 · 대상 결박 · 전달 경로 · 신원 복원 · 서명키는 게이트가 꺼져 있어도 그대로 동작한다. 게이트가 정하는 것은 **검증 실패를 거부로 옮길 것인가** 하나뿐이다.

**비차단 복원 경로는 이 게이트를 보지 않는다.** 그 경로는 어느 쪽이든 요청을 막지 않으며 차단은 소유자 검증이 정한다.

- 근거 자리 — `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:49` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:54` · `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.guard.ts:57`

## 연혁

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

| 릴리스 | 날짜 | SHA | 변경 요약 |
|---|---|---|---|
| — | 2026-07-01 | `55c4eaac` | 열람 단명토큰 신설 — 발급·결박·검증 축이 생긴 시점 |
| — | 2026-07-01 | `aa4d5b9e` | 관리자 콘솔이 발급받아 질의 인자로 싣는 경로 도입 |
| — | 2026-07-01 | `0baaa7a8` | 열람 화면이 최초 1회 캡처해 헤더로 붙이는 경로 도입 |
| — | 2026-07-06 | `33b0cd06` | 검증 가드의 의존 결선 정정 |
| — | 2026-07-20 | `f0038eb9` | 서명에 관리자 신원과 자동차 열람 여부가 함께 실림 |
| — | 2026-07-24 | `54473012` | 발급 입구에 기업별 노출 등급 요구가 결선됨 |
| — | 2026-07-31 | `799cdd7a` | 소유자 검증에 관리자 열람 통과 경로 추가 |
| — | 2026-07-31 | `482f60df` | 공용 조회의 비차단 신원 복원 경로 추가 |
| — | 2026-07-31 | `83568062` | 헤더 부착 대상 접두 목록에 공용 조회가 추가됨 |
