Governance
거버넌스
한국 엔터프라이즈 규제 환경을 전제로 설계했습니다 — 프롬프트 본문은 저장하지 않고, 개인정보는 게이트웨이를 떠나기 전에 마스킹하며, 조직·팀(부서)·키 3단계 예산과 조직 맞춤 가드레일(맞춤 PII 패턴 · 금지어 · 모델 정책)로 지출과 데이터를 통제합니다. 설정은 admin API 또는 대시보드의 거버넌스 관리 콘솔에서 합니다.
ZDR — Zero Data Retention
게이트웨이는 프롬프트·응답 본문을 데이터베이스에 저장하지 않습니다. 사용량 원장(usage ledger)과 감사 기록에는 메타데이터만 남습니다:
ts·keyId·orgId·endpointmodel·provider·tierpromptTokens·completionTokens·costUsd·savedUsdcacheHit·latencyMs·status
내부 디버그 로깅도 같은 정책을 따릅니다 — content, messages, input, prompt 필드는 로그 직전에 "[ZDR]"로 치환됩니다. 옵저버빌리티로 내보내는 값도 메타데이터뿐입니다.
PII 마스킹
마스킹은 유효 가드레일 정책의 detectors.pii가 켜져 있을 때 동작합니다 — 조직(governance.guardrails)이나 키(guardrails)에 설정하거나, 거버넌스 콘솔에서 켭니다. 기본값은 꺼짐이라, 가드레일 정책이 없는 키는 아무것도 가리지 않습니다. 켜고 나면 요청이 업스트림으로 나가기 전에 아래 5종을 유형별 토큰으로 치환합니다.
| 유형 | 패턴 | 치환 토큰 |
|---|---|---|
| 주민등록번호 (RRN) | YYMMDD-NNNNNNN — 날짜 유효성 검사 포함 | [MASKED:RRN] |
| 신용카드 | 13–19자리 (공백/대시 허용), Luhn 체크섬 통과 시에만 | [MASKED:CARD] |
| 휴대전화 | 01[016789]-XXXX-XXXX, +82 국제 표기 포함 | [MASKED:PHONE] |
| 이메일 | 표준 이메일 형식 | [MASKED:EMAIL] |
| 여권번호 | M/S + 8자리 숫자 | [MASKED:PASSPORT] |
입력: 제 번호는 010-1234-5678이고 메일은 kim@acme.co.kr입니다
전송: 제 번호는 [MASKED:PHONE]이고 메일은 [MASKED:EMAIL]입니다- 마스킹 순서는 RRN → CARD → PHONE → EMAIL → PASSPORT로 고정되어 오탐(카드 번호 속 전화번호 모양 등)을 방지합니다.
- 키 단위 on/off — 키 레코드의
piiMasking플래그로 제어하고, 요청 단위로는warp.no_pii_mask로 끌 수 있습니다. - 마스킹된 개수는 응답 메타
pii_masked로 확인합니다. - 마스킹은 단방향입니다 — 게이트웨이는 원문 복원용 매핑을 보관하지 않습니다 (ZDR).
조직 맞춤 패턴 · 금지어
기본 5종 외에, 조직이 직접 정의하는 정책을 org 레코드의 governance.guardrails에 등록할 수 있습니다. 키에 guardrails가 설정돼 있으면 키가 우선합니다 (키 재정의 → 조직 정책 → 게이트웨이 기본값).
| 필드 | 내용 |
|---|---|
pii.entities | 기본 5종 개별 on/off — 예: { "EMAIL": false }는 이메일만 마스킹 제외 |
pii.custom | 맞춤 정규식 패턴 (최대 64개) — { "name": "EMPLOYEE_ID", "pattern": "EMP-\\d{6}" }. 매칭 구간은 [MASKED:EMPLOYEE_ID]로 치환. 잘못된 정규식·과도하게 느린 패턴은 등록 시점에 400으로 거부됩니다. |
bannedWords | 금지어 목록 (최대 500개, 대소문자 무시 부분 일치) — 기본은 정책 mode를 따르고, 항목별 action으로 차단/가림/기록만을 개별 지정할 수 있습니다. action: "block" 항목은 정책이 mask/shadow여도 항상 차단합니다. |
모델 정책
조직/키 단위로 사용할 수 있는 모델을 제한합니다 — org의 governance.models 또는 키의 modelPolicy에 blockedModels/allowedModels를 등록합니다 (키가 우선, 차단이 허용보다 우선, 허용 목록이 비어 있으면 전체 허용). 항목은 카탈로그 모델 id, openai/* 같은 네임스페이스 와일드카드, warp 가상 id를 지원합니다.
- 차단된 모델을 직접 지정하면
403(model_blocked)로 거부됩니다 — chat·embeddings·이미지· 오디오 전 표면에 적용됩니다. warp/auto라우팅은 차단된 모델을 후보에서 제외하고 허용된 모델로 우회합니다 — 한 티어가 전부 차단되면 위 티어로 올라갑니다.GET /v1/models는 키의 유효 정책이 반영된 목록만 반환합니다 — 차단된 모델은 카탈로그에서 보이지 않습니다.
티어드 가드레일 스택
위 PII 마스킹은 가드레일 스택의 1단계입니다. 요청은 업스트림으로 나가기 전에 빠른 것부터 순서대로 아래 탐지기를 통과합니다 — 저렴한 정규식 단계가 대부분을 걸러내고, 비싼 단계는 필요할 때만 켭니다. 탐지기별 on/off는 키의 guardrails.detectors 정책으로 제어합니다 (API 레퍼런스 참조).
| 단계 | 탐지기 | 지연 | 내용 |
|---|---|---|---|
| 1 | 구조적 PII detectors.pii | sub-ms | 정규식 — 주민등록번호·카드(Luhn)·전화·이메일·여권 (위 표와 동일) |
| 2 | 시크릿 / 엔트로피 detectors.secrets | ~1–2ms | API 키·클라우드 토큰 패턴 + 고엔트로피 문자열 (유출 크리덴셜) |
| 3 | Presidio NER detectors.presidio | 외부 호출 | 비정형 PII(이름·주소·조직) — 외부 Presidio 인스턴스, PRESIDIO_URL 설정 시에만 활성화 |
| 4 | 프롬프트 인젝션 휴리스틱 detectors.injection | sub-ms | jailbreak·명령 재정의 패턴 스크리닝 — Prompt Guard 2 연동 포인트 |
적용 모드 3종
무엇을 탐지할지와 별개로, 탐지 결과를 어떻게 처리할지는 키의 guardrails.mode로 정합니다.
| 모드 | 이름 | 동작 |
|---|---|---|
block | Validation | 위반 발견 시 요청을 즉시 거부합니다 — 본문 대신 위반 카테고리 요약만 반환됩니다. |
mask | Mutation | 탐지된 구간을 [MASKED:*] 토큰으로 자동 마스킹한 뒤 업스트림으로 전달합니다 (단방향, 복원 불가). |
shadow | Shadow | 요청은 그대로 통과시키고 탐지 결과만 Audit Trail에 기록(감사만)합니다 — 정책 도입 전 드라이런에 적합합니다. |
어느 모드든 요청별 결과는 응답 메타 guardrails.findings와 x-warp-guardrail-findings 헤더로 확인합니다 — 건수와 카테고리만 담기며 원문은 담기지 않습니다 (ZDR).
스트리밍 출력 가드레일
키에 guardrails.streamOutput이 켜져 있으면 모델의 출력도 검사합니다 — SSE 청크를 슬라이딩 버퍼에 모아 경계에 걸친 패턴까지 증분 검증하므로, 토큰 단위로 쪼개진 주민등록번호나 시크릿도 놓치지 않습니다. 위반이 확인되면 스트림을 finish_reason: "content_filter"로 즉시 중단합니다.
Audit Trail
모든 가드레일 판정은 불변(append-only) 메타데이터 로그로 남습니다 — 모드, 카테고리별 탐지 건수, 차단 여부, 요청 id만 기록되고 프롬프트·응답 본문은 저장되지 않습니다 (ZDR). 조회는 GET /admin/audit로 합니다 (API 레퍼런스 참조).
BYOK — Bring Your Own Key
조직이 이미 보유한 업스트림 계약(OpenAI, Anthropic 등)을 그대로 쓸 수 있습니다. 프로바이더별로 키를 등록하면, 해당 프로바이더 호출 시 플랫폼 공용 키 대신 조직의 키가 사용됩니다 — chat, embeddings, 이미지·음성까지 전부 적용됩니다.
가장 간단한 방법은 콘솔의 BYOK 탭입니다 (소유자 전용, 프로바이더별 입력칸). 조직 단위로 저장되며, 특정 키만 다른 계정을 쓰게 하려면 admin API의 키 레코드 byokKeys로 프로바이더별 override를 겁니다. 저장된 키는 서버에서 암호화되어 보관되고, 조회 시에는 절대 다시 반환되지 않습니다 (어떤 프로바이더가 연결됐는지만 표시).
수수료는 BYOK에도 동일하게 적용됩니다. 자기 키로 처리된 요청도 이용 금액만큼 플랫폼 수수료 5%가 크레딧에서 차감되며, 크레딧이 없으면 요청이 402로 막힙니다. 이때 이용 금액은 Warp 카탈로그 가격 기준의 명목가로 산정합니다 — 프로바이더와 따로 협상한 단가나 구독제를 쓰더라도, 수수료 산정 기준은 카탈로그 가격이며 실제 프로바이더 청구액과 다를 수 있습니다.
admin API로 등록하는 예시 (마스터 키 필요, 자세한 스키마는 API 레퍼런스 참조):
curl -X POST https://api.warp.inc/admin/keys \
-H "Authorization: Bearer $WARP_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"orgId": "org_abc123",
"name": "prod-backend",
"piiMasking": true,
"zdr": true,
"byokKeys": {
"openai": "sk-proj-…",
"anthropic": "sk-ant-…"
}
}'예산 정책 — 조직 · 팀(부서) · 키
예산은 UTC 달력 월 기준으로 집계되며, 조직 → 팀(부서) → 키 세 단계로 겁니다. null은 무제한을 의미합니다. 키는 teamId로 팀에 소속시키고, 팀 지출은 요청 시점 소속으로 기록됩니다 — 키를 다른 팀으로 옮겨도 과거 지출은 원래 팀에 남습니다.
| 범위 | 초과 시 동작 |
|---|---|
| 조직 예산 | 하드 캡 — 항상 402 (budget_exceeded)로 거부합니다. 팀·키 정책과 무관하게 우선합니다. |
| 팀(부서) 예산 | 팀의 overBudgetBehavior를 따릅니다 — "reject"는 402로 거부, "downgrade"는 Tier 3로 강제 전환. 팀과 키가 동시에 초과하면 더 엄격한 판정이 이깁니다. |
| 키 예산 | 키의 overBudgetBehavior를 따릅니다 — "reject"는 402로 거부, "downgrade"는 티어를 3으로 강제해 저비용으로 계속 서비스합니다. |
downgrade는 모든 경로에 적용됩니다. 강제된 티어는 지출 상한으로 걸리므로, 특정 모델을 명시한 요청도 상한을 넘으면 그 모델 대신 강제 티어의 라우팅을 타게 됩니다 — 모델 이름을 하드코딩한 클라이언트만 예산 하향을 비껴가던 문제를 막기 위해서입니다.- 임베딩에는 다운그레이드 개념이 없습니다 — 예산 초과 시
402로만 거부됩니다.