---
template: policy-doc@1
doc_id: 02-ttl-and-timeouts
title: 시간 한도 — 유효 기간이 어디서 시작하고 무엇이 그것을 덮는가
config: ../_meta/template-config.yaml
last_verified: 4d798f55
policies:
  - id: limits:certify-window-triplet
    status: active-prod
    evidence: [S-constant, S-guard]
    limitations:
      - 세 창의 기본값은 코드에서 읽었으나 운영 환경이 실제로 어떤 값을 넣고 있는지는 확보하지 않았다. 여기 적은 수는 설정이 없을 때의 값이다
    anchors:
      - insuniverse-server/apps/api/src/modules/treat/treat.service.ts:71
      - insuniverse-server/apps/api/src/modules/treat/treat.service.ts:73
      - insuniverse-server/apps/api/src/modules/treat/treat.service.ts:75
      - insuniverse-server/apps/api/src/modules/treat/treat.service.ts:279
      - insuniverse-server/apps/api/src/modules/treat/treat.service.ts:153
      - insuniverse-server/apps/api/src/modules/treat/treat.service.ts:165
  - id: limits:dispatch-stage-windows
    status: active-prod
    evidence: [S-constant, S-guard]
    anchors:
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:41
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:42
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:43
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-reservation.service.ts:176
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:159
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:177
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:333
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-reservation.service.ts:233
  - id: limits:queue-two-liveness-windows
    status: active-prod
    evidence: [S-constant, S-guard]
    anchors:
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:12
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:16
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:76
      - insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:77
  - id: limits:provider-setting-cache-window
    status: active-prod
    evidence: [S-constant, S-guard]
    anchors:
      - insuniverse-server/apps/api/src/modules/treat/provider/treat-provider.service.ts:17
      - insuniverse-server/apps/api/src/modules/treat/provider/treat-provider.service.ts:54
  - id: limits:vendor-timeout-table-is-reference-only
    status: active-prod
    evidence: [S-constant, S-route]
    limitations:
      - 표 안의 벤더별 값은 이 문서가 옮기지 않는다. 그 해석은 벤더 축 문서의 소유다. 여기서는 표가 실재하고 아무것도 강제하지 않는다는 사실까지만 든다
    anchors:
      - insuniverse-server/apps/api/src/modules/treat-test/reference/flows.ts:45
      - insuniverse-server/apps/api/src/modules/treat-test/treat-test.controller.ts:118
  - id: limits:admin-view-window-default
    status: conditional-unknown
    evidence: [S-constant, S-guard]
    unknown_reason: 창 길이를 덮는 환경 설정의 운영값을 이 조사가 확보하지 않았다. 코드는 설정이 없을 때 쓸 값을 정할 뿐이며 운영에서 그 값이 실제로 쓰이는지 판정하지 못한다
    anchors:
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:25
      - insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:35
  - id: limits:monitor-cache-windows
    status: staged-only
    evidence: [S-constant, S-guard]
    limitations:
      - 이 정책의 선언 여섯과 그것을 무는 분기 하나가 전부 아직 운영에 닿지 않은 변경에서 왔다. 운영에서 이 창들이 어떻게 도는지는 관측하지 않았다
    anchors:
      - insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:100
      - insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:103
      - insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:715
      - insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:716
      - insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:717
      - insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:981
      - insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:742
---

# 시간 한도 — 유효 기간이 어디서 시작하고 무엇이 그것을 덮는가

이 문서는 **한 번의 유효 기간**만 다룬다. 무엇이 언제까지 살아 있는가, 그 창이 끝나면 무엇이 회수
되는가 두 축이다. 단위 시간당 몇 번이나 한 번에 몇 개는 이 문서의 축이 아니다 — 빈도·묶음 문서가
든다.

읽는 사람이 여기서 얻어야 하는 것은 **창이 하나가 아니라는 사실**이다. 한 요청이 살아 있는 동안
서로 다른 창 여럿이 겹쳐 돌고, 그중 짧은 것이 먼저 끝나면 요청 전체가 아니라 그 단계의 자격만
사라진다. 어느 창이 먼저 끝나는지를 모르면 "왜 갑자기 처음으로 돌아갔는가" 에 답할 수 없다.

**설정이 값을 덮는 정책은 둘이다** — 인증 창 세 벌과 관리자 열람 토큰 창이며, 둘 다 이 문서가 적은
수는 설정이 없을 때의 값이다. 운영 환경이 실제로 어떤 값을 넣고 있는지는 이 조사가 확보하지 않았다.
기본값을 운영값으로 읽으면 틀린다.

문서 트리의 설명 행은 이 문서에 시간 상수 두 이름을 배치했으나, 실측이 그 배치를 반증한다. 하나는
시간값이 없는 오류 분류 어휘이고, 다른 하나는 실재하지만 값이 산문이고 아무것도 강제하지 않는
참조표다. 세 번째 이름은 기능 게이트 정본 목록의 원소라 이 문서가 그 이름을 쓸 수 없다 — 기전과
앵커까지만 적고 이름과 운영 상태는 기능 게이트 문서로 넘긴다. 설명 행을 그대로 따르지 않은 이유가
이것이다.

여기 없는 것: 금액과 개수의 상한, 단위 시간당 횟수와 묶음 크기, 벤더별 대기 시간의 해석, 오류 분류
어휘의 뜻, 스케줄 주기, 기능 게이트의 운영 활성 여부. 각각 다른 문서의 소유다.

## 정책 (기획)

### limits:certify-window-triplet

진료 정보 인증은 창 셋을 겹쳐 쓴다. **점유 창**은 같은 사람의 인증이 이미 진행 중이라고 볼 기간
이고 6분이다. **재개 창**은 화면을 떠났다 돌아왔을 때 이어서 진행할 수 있는 기간이고 5분이다.
**일회용 번호 창**은 문자로 받은 번호가 유효한 기간이고 170초다.

셋은 서로 다른 것을 지킨다. 점유 창은 같은 사람이 인증을 여러 번 겹쳐 걸어 자원을 낭비하지 않게
하고, 재개 창은 잠깐 이탈한 사람이 처음부터 다시 하지 않게 하며, 일회용 번호 창은 외부 인증 기관이
정한 시간에 맞춘다.

**세 값은 설정으로 덮인다.** 코드는 설정이 없을 때 쓸 값을 정할 뿐이며 운영 환경이 다른 값을 넣고
있을 수 있다. 이 문서는 그 운영값을 확보하지 않았으므로 여기 적은 수를 운영 한도로 읽으면 안 된다.

**점유 창은 인증 세션 전체를 잠그는 것이 아니다.** 첫 호출이 응답을 돌려주는 자리에서 점유가 풀리고,
위에 적은 그 기간은 해제가 일어나지 못했을 때만 남는 백업 만료다. 다만 개인이 직접 들어오는 갈래는
그 해제를 건너뛰므로 그 갈래에서만 점유 창이 실제로 남는다.

이용자에게 만드는 결과: 인증 도중 화면을 벗어났다가 재개 창 안에 돌아오면 이어서 진행된다. 그보다
늦으면 처음으로 돌아간다. **번호 유효 시간**인 170초 안에 넣지 못하면 번호만 무효가 되고 인증은
대체로 곧바로 다시 걸 수 있다 — "다시 시도" 가 막히는 구간은 개인이 직접 들어오는 갈래에서 생긴다.

### limits:dispatch-stage-windows

외부 수집은 단계마다 다른 창을 잡는다. 슬롯을 예약한 뒤 **1차 호출 백업 창**이 6분, 사용자가 번호를
넣기를 기다리는 **번호 대기 창**이 3분, 번호를 넣은 뒤 실제 수집이 도는 **수집 창**이 7분이다.
그리고 대기열에서 순번이 와 자리를 잡은 사람이 실제 요청을 보낼 때까지 쥐는 **입장권 창**이 18초다.

창이 단계마다 다시 잡히는 것이 이 정책의 핵심이다. 다음 단계로 넘어갈 때 창을 새로 설정하므로,
앞 단계에서 남은 시간이 뒤 단계로 이월되지 않는다. 각 단계는 자기 창의 처음부터 시작한다.

입장권 창이 유독 짧은 것은 그것이 사람을 기다리는 창이 아니라 **왕복 한 번을 기다리는 창**이기
때문이다. 순번이 왔다는 응답을 받고 곧바로 다시 요청을 보내는 데 필요한 시간만 준다. 쓰지 않으면
자리는 자동으로 회수돼 다음 사람에게 간다.

이용자에게 만드는 결과: 번호 입력이 늦어 끊긴 경우와 수집이 오래 걸려 끊긴 경우는 다른 단계의
다른 창이며, 남은 시간도 다르게 흐른다. 사용자에게는 둘 다 실패로 보이지만 회수되는 자원이 다르다.

### limits:queue-two-liveness-windows

대기열은 창을 둘 쓴다. **큐 생존 창**은 대기 순번을 유지할 기간이고 90초다. **활성 창**은 자리를
배정받을 자격이 있다고 볼 기간이고 12초다.

뒤엣것이 훨씬 짧은 것이 이 정책의 축이다. 화면이 배경으로 내려가면 주기적 확인이 끊기는데, 그때
활성 창이 먼저 끝나 그 사람은 자리 배정 대상에서 빠진다. 하지만 큐 생존 창은 아직 살아 있어 **순번은
그대로 유지**된다. 돌아와서 다시 확인을 보내면 곧바로 활성 상태가 되고 순번을 잃지 않는다.

두 창을 하나로 합치면 둘 중 하나를 포기해야 한다. 짧게 잡으면 잠깐 화면을 끈 사람이 순번을 잃고,
길게 잡으면 배경으로 내려간 맨 앞 사람이 자리를 계속 막는다. 창을 둘로 가른 것이 그 둘을 함께
푸는 방법이다.

이용자에게 만드는 결과: 대기 중 다른 앱으로 옮겨 갔다 돌아와도 순번은 남아 있다. 다만 배경에 있는
동안에는 자리가 나도 배정되지 않고 다음 사람에게 간다.

창을 닫았을 때는 두 대기열이 다르게 움직인다. **일반 대기열은 즉시 빠지지 않는다** — 화면을 떠나는
자리에서 이탈을 부르지 않고 두 창의 만료에 맡긴다. 새로고침과 앱 복귀를 구별할 수 없어서 내린
판단이며, 그 대가로 닫힌 화면의 순번이 만료 전까지 남는다. 개인이 직접 들어오는 대기열만 창을
떠날 때 이탈을 한 번 시도하고, 그것도 보장이 아니라 최선을 다하는 시도다.

### limits:provider-setting-cache-window

공급자 설정은 **15초** 동안 캐시된다. 요청마다 저장소를 다시 읽지 않기 위한 창이다.

**관리자 화면을 거친 변경은 이 창을 기다리지 않는다.** 저장하는 자리가 곧바로 캐시를 버리므로 다음
요청이 저장소를 다시 읽는다. 창이 만드는 지연은 그 경로 밖의 변경 — 저장소를 직접 고치는 것처럼
캐시를 버릴 기회가 없는 변경 — 에만 남는다.

이 창은 앞의 것들과 성격이 다르다. 사용자의 자격이 아니라 **읽은 값의 신선도**를 정한다. 창이 끝나면
아무것도 회수되지 않고 다음 요청이 저장소를 다시 읽을 뿐이다.

이용자에게 만드는 결과: 관리자 화면으로 단가나 공급자 스위치를 바꾸면 그 직후 요청부터 새 설정으로
돈다. 옛 설정으로 도는 구간이 남는 것은 그 경로를 거치지 않은 변경뿐이며, 그때도 오류가 아니라
반영 지연이다.

### limits:vendor-timeout-table-is-reference-only

벤더별 인증 대기 시간과 세션 만료 시간을 담은 표가 실재한다. 벤더 넷의 두 축을 적고 있다.

**강제하지 않는 참조표는 하나뿐이다** — 이 표다. 값이 숫자가 아니라 산문이고, 그 산문을 읽어 무엇을
끊거나 기다리는 코드가 없다. 표는 관리자 전용 시험 화면이 그대로 돌려주는 자료일 뿐이다.

이 사실을 적어 두는 이유는 이름 때문이다. 이름만 보면 벤더별 대기 한도를 정하는 자리처럼 읽히고,
그렇게 읽으면 "이 값을 바꾸면 대기 시간이 바뀐다" 는 틀린 결론이 나온다. 실제 대기는 앞의 창들과
외부 기관 자신의 제한이 정하며, 이 표는 그것을 사람이 참고하도록 적어 둔 기록이다.

표 안의 벤더별 값은 이 문서가 옮기지 않는다. 그 해석은 벤더 축 문서의 소유다.

이용자에게 만드는 결과: 없다. 이 표는 이용자 경로에 등장하지 않는다.

## 강제 지점 (개발)

### limits:certify-window-triplet

세 창은 설정을 먼저 읽고 없으면 기본값을 쓰는 형태로 선언된다. 선언 자체는 강제가 아니라서 층이
`—` 이고, 실제로 무는 것은 그 값을 마감 시각 계산과 재개 판정에 넘기는 세 자리다.

- 슬롯 — CERTIFY_CLAIM_TTL_MS: 값 `360000` · 층 `—` · 출처 `설정 미지정 시` · 앵커 `insuniverse-server/apps/api/src/modules/treat/treat.service.ts:71`
- 슬롯 — CERTIFY_RESUME_TTL_MS: 값 `300000` · 층 `—` · 출처 `설정 미지정 시` · 앵커 `insuniverse-server/apps/api/src/modules/treat/treat.service.ts:73`
- 슬롯 — CERTIFY_OTP_TTL_MS: 값 `170000` · 층 `—` · 출처 `설정 미지정 시` · 앵커 `insuniverse-server/apps/api/src/modules/treat/treat.service.ts:75`
- 슬롯 — 점유 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/treat.service.ts:279`
- 슬롯 — 재개 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/treat.service.ts:153`
- 슬롯 — 일회용 번호 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/treat.service.ts:165`

### limits:dispatch-stage-windows

세 단계 창은 디스패처 머리에 상수로 있고 입장권 창은 예약 서비스의 정적 필드다. 무는 자리는 각
단계에서 슬롯 만료를 다시 설정하는 호출이다.

- 슬롯 — RESERVE_TTL_MS: 값 `360000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:41`
- 슬롯 — OTP_TTL_MS: 값 `180000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:42`
- 슬롯 — COLLECT_TTL_MS: 값 `420000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:43`
- 슬롯 — ADMIT_TTL_MS: 값 `18000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-reservation.service.ts:176`
- 슬롯 — 1차 호출 백업 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:159`
- 슬롯 — 번호 대기 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:177`
- 슬롯 — 수집 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-dispatcher.service.ts:333`
- 슬롯 — 입장권 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-reservation.service.ts:233`

### limits:queue-two-liveness-windows

두 창은 같은 파일 머리에 나란히 선언되고, 대기열 진입과 주기적 확인 시점에 각각 다른 키의 만료로
설정된다. 키가 둘이라 창도 둘로 흐른다.

- 슬롯 — ALIVE_MS: 값 `90000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:12`
- 슬롯 — ACTIVE_MS: 값 `12000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:16`
- 슬롯 — 큐 생존 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:76`
- 슬롯 — 활성 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/dispatch/treat-queue.service.ts:77`

### limits:provider-setting-cache-window

상수 하나와 그것을 무는 비교 하나다. 캐시가 있고 경과 시간이 창보다 짧으면 저장소를 읽지 않는다.

- 슬롯 — CACHE_TTL_MS: 값 `15000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/provider/treat-provider.service.ts:17`
- 슬롯 — 캐시 창 소비: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/provider/treat-provider.service.ts:54`

### limits:vendor-timeout-table-is-reference-only

표는 벤더 이름을 키로 갖는 객체이고 값이 전부 문자열이다. 관리자 전용 시험 표면이 그 객체를 그대로
응답에 실어 돌려준다. 층이 `없음` 인 것은 이 정책의 주장이며, 그 주장은 동결 트리에서 이 이름이
등장하는 모든 행에 비교 연산이나 예외 발생이 없음을 다시 확인해 검사한다.

- 슬롯 — VENDOR_TIMEOUTS: 값 `4` · 층 `없음` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat-test/reference/flows.ts:45`
- 슬롯 — 관리자 시험 표면 반환: 값 `—` · 층 `없음` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat-test/treat-test.controller.ts:118`

### limits:admin-view-window-default

창 길이는 설정을 먼저 읽고 없으면 기본값을 쓴다. 발급 시점에 그 값을 더해 만료 시각을 계산하고
서명에 함께 싣는다. 서명 비밀이 둘 다 비어 있으면 키가 빈 문자열이 되어 검증이 항상 실패한다 —
창 길이와 무관하게 안전한 쪽으로 닫힌다.

- 슬롯 — ttlMs: 값 `600000` · 층 `—` · 출처 `설정 미지정 시` · 앵커 `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:25`
- 슬롯 — 만료 시각 계산: 값 `—` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/admin-view-token/admin-view-token.service.ts:35`

### limits:monitor-cache-windows

관리자 집계 화면의 캐시 창 여섯과 조회 기간 상한 하나다. 상한만 분기로 물고 나머지는 캐시 판정에
쓰인다. 일곱 자리 전부 아직 운영에 닿지 않은 변경에서 왔다.

- 슬롯 — OVERVIEW_TTL_MS: 값 `12000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:100`
- 슬롯 — MONTHLY_TTL_MS: 값 `60000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:103`
- 슬롯 — DAILY_TTL_MS: 값 `60000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:715`
- 슬롯 — DAILY_TTL_PAST_MS: 값 `600000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:716`
- 슬롯 — DAILY_MAX_SPAN_DAYS: 값 `92` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:717`
- 슬롯 — ENTERPRISE_TTL_MS: 값 `300000` · 층 `—` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:981`
- 슬롯 — 범위 상한 가드: 값 `92` · 층 `서비스 가드` · 출처 `고정값` · 앵커 `insuniverse-server/apps/api/src/modules/treat/monitor/treat-monitor.service.ts:742`

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

| 정책 id | 관리자 | 영업대리점 | 기업담당자 | 일반회원 | 기업회원 | server | site | admin |
|---|---|---|---|---|---|---|---|---|
| limits:certify-window-triplet | — | — | 적용 | 적용 | 적용 | 강제 지점 | — | — |
| limits:dispatch-stage-windows | — | — | 적용 | 적용 | 적용 | 강제 지점 | — | — |
| limits:queue-two-liveness-windows | — | — | 적용 | 적용 | 적용 | 강제 지점 | — | — |
| limits:provider-setting-cache-window | 적용 | — | — | — | — | 강제 지점 | — | — |
| limits:vendor-timeout-table-is-reference-only | 적용 | — | — | — | — | — | — | — |
| limits:admin-view-window-default | 적용 | — | — | — | — | 강제 지점 | — | — |
| limits:monitor-cache-windows | 적용 | — | — | — | — | 강제 지점 | — | — |

서비스 열 셋은 기계가 대조한다. 강제 자리를 가진 정책은 전건 서버 한 저장소에서만 걸린다 — 창의 시작과
끝을 정하는 자리가 화면 쪽에 없다는 뜻이며, 화면은 창이 끝났다는 응답을 받아 표시할 뿐이다.
클라이언트가 자기 판단으로 포기하는 횟수와 주기는 이 문서의 축이 아니라 빈도 문서의 축이다.
세 열이 모두 빈 행이 있다 — 아무것도 강제하지 않는 참조 자료라 어느 저장소에도 강제 자리가 없다.

actor 다섯 열은 대조 밖이다. 권한 모델을 동결 트리에서 되짚을 경로가 이 조사에 없다.

## 예외·폴백

| 정책 id | 예외 조건 | 폴백 동작 | 확인 근거 |
|---|---|---|---|
| limits:certify-window-triplet | 설정이 창 길이를 덮음 | 코드 기본값 대신 설정값이 쓰인다. 이 문서의 수는 설정이 없을 때의 값이다 | `treat.service.ts:71` |
| limits:certify-window-triplet | 재개 창은 지났는데 점유 창은 남음 | 이어서 진행할 수 없고 새로 시작할 수도 없는 구간이 생긴다 | `treat.service.ts:153` · `treat.service.ts:279` |
| limits:dispatch-stage-windows | 다음 단계로 넘어감 | 창이 새로 설정된다. 앞 단계의 남은 시간은 이월되지 않는다 | `treat-dispatcher.service.ts:177` |
| limits:dispatch-stage-windows | 입장권을 받고 쓰지 않음 | 자리가 자동으로 회수돼 다음 사람에게 간다 | `treat-reservation.service.ts:233` |
| limits:queue-two-liveness-windows | 화면이 배경으로 내려가 확인이 끊김 | 활성 창이 먼저 끝나 자리 배정에서 빠지고 순번은 유지된다 | `treat-queue.service.ts:77` |
| limits:queue-two-liveness-windows | 창을 닫음 — 일반 대기열 | 이탈을 부르지 않는다. 두 창이 만료돼야 빠진다 | `treat-queue.service.ts:12` · `treat-queue.service.ts:16` |
| limits:queue-two-liveness-windows | 창을 닫음 — 개인이 직접 들어온 대기열 | 이탈을 한 번 시도한다. 보장이 아니라 최선의 시도다 | `treat-queue.service.ts:76` |
| limits:provider-setting-cache-window | 캐시가 아직 유효 | 저장소를 읽지 않고 캐시 값을 쓴다. 설정 변경 반영이 그만큼 늦다 | `treat-provider.service.ts:54` |
| limits:vendor-timeout-table-is-reference-only | 표의 값을 바꿈 | 아무 동작도 바뀌지 않는다. 강제하는 자리가 없다 | `flows.ts:45` |
| limits:admin-view-window-default | 서명 비밀이 둘 다 없음 | 키가 비어 검증이 항상 실패한다. 창 길이와 무관하게 닫힌다 | `admin-view-token.service.ts:35` |
| limits:monitor-cache-windows | 조회 기간이 상한을 넘음 | 시작일을 상한만큼 당겨 잘라 조회한다. 거절이 아니다 | `treat-monitor.service.ts:742` |

## 부록

이 절의 정책 둘은 각각 다른 이유로 본문에서 격리된다. 하나는 **값을 덮는 설정의 운영 상태를
확보하지 못했고**, 다른 하나는 **아직 운영에 닿지 않았다**. 본문에 두면 독자가 지금 확정된 사실로
읽는다. 확보되거나 배포가 닿으면 표기가 바뀌고 배치도 함께 본문으로 옮긴다.

### limits:admin-view-window-default

관리자가 다른 화면으로 넘어갈 때 쓰는 열람 토큰에는 유효 기간이 있다. 설정이 없으면 10분이다.

이 정책을 부록에 두는 이유는 값이 아니라 **값을 정하는 주체** 때문이다. 창 길이는 설정으로 덮이는데
운영 환경이 어떤 값을 넣고 있는지를 이 조사가 확보하지 않았다. 따라서 운영에서 이 창이 실제로 얼마
인지 이 문서는 말하지 않는다. 코드가 정하는 것은 설정이 없을 때의 값뿐이다.

값과 무관하게 확정된 사실이 하나 있다. 서명 비밀이 둘 다 비어 있으면 검증이 항상 실패한다. 창이
길든 짧든 그 상태에서는 토큰이 통하지 않는다.

이용자에게 만드는 결과: 관리자가 열람 화면을 오래 열어 두면 다시 들어갈 때 만료로 막힐 수 있다.
막히는 시점이 언제인지는 운영 설정에 달려 있다.

### limits:monitor-cache-windows

관리자 집계 화면은 새로 고침을 여러 번 눌러도 실제 계산이 창마다 한 번만 돌도록 결과를 캐시한다.
화면마다 창이 다르다 — 실시간 개요가 12초, 월 단위와 오늘이 포함된 일별이 60초, 지나간 구간의
일별이 10분, 기업 단위가 5분이다. 한 번에 조회할 수 있는 기간에도 상한이 있어 92일을 넘으면 시작일을
당겨 자른다.

지나간 구간의 창이 훨씬 긴 것은 그 구간의 숫자가 더 이상 변하지 않기 때문이다. 오늘이 포함된
구간만 짧게 잡아 새 데이터가 들어오는 만큼 반영한다.

이 정책을 부록에 두는 이유는 일곱 자리 전부 **아직 운영에 닿지 않은 변경**에서 왔기 때문이다. 지금
상태를 본문에 적으면 독자가 운영에서 이미 이렇게 동작한다고 읽는다. 배포가 닿으면 표기가 바뀌고
배치도 본문으로 옮긴다.

이용자에게 만드는 결과: 관리자만 본다. 배포가 닿은 뒤 집계 숫자가 새로 고침 직후에 바뀌지 않는
구간이 생기며, 그것은 지연이지 오류가 아니다.

## 연혁

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

| 릴리스 | 날짜 | SHA | 변경 요약 |
|---|---|---|---|
| — | 2026-06-05 | `42fb6e77` | 공급자 설정 캐시 창이 단가 설정과 함께 들어왔다 |
| — | 2026-06-07 | `12c1c89f` | 수집 단계별 창 셋이 갈라졌다 |
| — | 2026-06-07 | `105822f4` | 대기열 입장권 창이 새치기 차단과 함께 생겼다 |
| — | 2026-06-07 | `2296e03a` | 벤더 대기·세션 참조표가 관리자 전용 시험 표면에 실렸다 |
| — | 2026-06-08 | `e47e6c14` | 큐 생존 창이 배경 이탈 오판을 줄이려 길어졌다 |
| — | 2026-06-08 | `f79a8f4f` | 자리 배정 자격이 활성 창으로 분리됐다 |
| — | 2026-07-01 | `55c4eaac` | 관리자 열람 토큰과 그 창이 생겼다 |
| — | 2026-07-07 | `9de69e28` | 인증 점유 창이 중복 시작 차단으로 들어왔다 |
| — | 2026-07-12 | `f3a4fb3c` | 재개 창이 예약 슬롯 창과 정렬됐다 |
| — | 2026-07-12 | `84178880` | 재개와 일회용 번호 창의 만료 처리가 정리됐다 |
| — | 2026-07-13 | `7d9295dc` | 실시간 개요 캐시 창이 신설됐다 |
| — | 2026-07-13 | `0ba5dd06` | 월 단위 집계와 그 캐시 창이 신설됐다 |
| — | 2026-07-21 | `c93548bc` | 일별 집계와 기간 상한·과거 구간 장기 창이 신설됐다 |
