Skip to content

AI Guard 정책

판옵티콘이 본 것을 정책으로 막는 것이 AI Guard입니다. 베타 기준으로 4종 정책 중 일부는 구현되어 있고, 일부는 설계 단계입니다.

AI 에이전트에게 얼마나 많은 권한을 줄지, 이탈했을 때 어떻게 멈출지를 정하는 것이 AI Guard가 존재하는 이유입니다. 이는 정부가 '에이전틱 AI 이니셔티브'에서 강조한 AI 에이전트 권한 관리·인간 감독 체계와 같은 방향입니다.

🔬 일부 정책은 설계 단계입니다

이 페이지가 다루는 4종 정책 중 Soft Kill Switch CLI 는 현재 코드베이스에 구현되지 않았습니다. logi 서버는 다음을 아직 제공하지 않습니다:

  • logi panopticon kill <client_id> CLI — 미구현
  • OauthApplication#killed_at 등 kill switch 상태 컬럼 — 미구현

HITL 승인의 사용자 결정 화면은 스토어 배포분에 아직 반영 전입니다. 서버 쪽(POST /panopticon/approvals — 복수형입니다. /panopticon/approval/request 는 존재한 적이 없습니다)은 요청 생성부터 폰 푸시 전달까지 동작하고, 앱 승인 화면과 approval_url(/approvals/<uuid>) 딥링크도 구현돼 있습니다. 앱 미설치·구버전 사용자는 그 URL 에서 정적 안내 페이지를 만납니다. RP 통합 시에는 승인이 오지 않는 경우(사용자가 결정 화면에 아직 닿지 못하는 구버전 앱)를 정상 경로로 다루세요 — TTL 5분 만료 후 expired 를 받는 흐름이 그 케이스입니다.

도구별 opt-in 목록(hitl_required_tools)은 개발자 콘솔의 앱 편집 화면에서 직접 설정할 수 있습니다(한 줄에 도구 하나). 운영자 문의는 더 이상 필요하지 않습니다.

프로덕션에서 사용자 승인이 실제로 필요하면 Agent Approval Gate를 쓰세요 — 그쪽은 앱 화면까지 완비돼 있습니다.

현재 동작 가능한 정책: Scope Drift Policy 3단계 전체 — 기본값은 block(2026-06-10부터)이라 미등록 scope는 /oauth/authorize에서 invalid_scope로 거절됩니다(log_only 완화는 운영자 admin API로만 설정). Rate Limit (rack-attack 단의 /oauth/token·/oauth/userinfo throttle). HITL 승인. 그 외는 enforcement 미연동입니다. 진행 상황 문의는 support@1pass.dev 로 보내주세요.

정책 한눈에

정책즉시성RP 측 부담상태
Rate Limit (rack-attack /oauth/*)즉시 (서버)없음✓ 구현 완료
Rate Limit (per-application × tool)즉시 (서버)webhook 수신🔬 설계 중
Soft Kill Switch≤ 15분없음🔬 설계 중
HITL 승인사용자 응답 시endpoint 추가 호출🔬 서버 브로커 + 푸시 전달 구현. 도구 목록은 개발자 콘솔에서 직접 설정. 앱 승인 화면·딥링크도 배선 완료지만 스토어 배포분에는 아직 반영 전
Scope Drift Policy (block 기본 / alert / log_only)즉시 (/oauth/authorize)없음✓ 구현 완료 — 정책 변경은 운영자 admin API, 콘솔 토글·CLI는 로드맵

베타에서는 정책 설정·집행은 가능하지만 quota 강제와 과금은 비활성입니다 (구현된 정책 한정).


1. Rate Limit

LLM 환각으로 인한 도구 호출 폭주 방어.

두 종류의 Rate Limit이 존재하며 적용 지점이 다릅니다.

A. logi endpoint throttle (rack-attack 기존)

/oauth/token, /oauth/userinfo 등 logi가 직접 호스팅하는 endpoint에 대한 보호. application/IP 단위.

B. AI Guard tool throttle (Panopticon 신규) 🔬 (설계 단계)

미구현 — 설계 사양

아래 (application × user, application × tool) 카운팅·webhook 발사와 override CLI는 아직 구현되지 않았습니다. 현재 동작하는 Rate Limit은 위 A(rack-attack)뿐입니다.

RP가 trace를 보고하는 application에 대해 Panopticon이 logi 측에서 카운팅하는 (application × user, application × tool) 한도. 한도 초과 시 logi는 webhook(panopticon.anomaly_detected)을 발사하고, RP는 자기 정책에 따라 차단/경고를 결정합니다. logi가 도구 호출 자체를 막지는 않습니다 — RP는 webhook을 받아 자기 측에서 차단해야 합니다.

기본값 (per application × user):

  • 분당 60회
  • 동일 도구 분당 20회

override (콘솔 또는 CLI):

bash
logi panopticon policy <client_id> --rate-limit '{"per_minute":120,"per_tool_per_minute":40}'

2. Soft Kill Switch 🔬 (설계 단계)

미구현 — 설계 사양

아래 발동 절차 (CLI · 콘솔 1-click) 는 logi 서버에 아직 라우트가 없습니다. OauthApplication#killed_at 컬럼, logi panopticon kill CLI 명령, 콘솔 Kill Switch 탭 모두 backlog 입니다.

현재 가능한 차단 수단:

  • Refresh token 회전+재사용 탐지: 이미 구현됨 (Oauth::TokensController#rotate_refresh_token + OauthAccessToken#revoke_chain!). 재사용 감지 시 chain 전체가 자동 revoke 되므로, 도난 시나리오에서는 사실상 즉시 차단 효과.
  • 수동 DB revoke: OauthAccessToken.where(oauth_application_id: APP_ID).find_each(&:revoke!) 콘솔 실행. RT 가 revoke 되면 다음 회전 시도에서 거부.

특정 application 또는 (application × user) 단위 즉시 차단.

발동 (계획)

콘솔 → application → Kill Switch 탭 → 사용자 매트릭스에서 1-click

또는 CLI:

bash
logi panopticon kill <client_id>                    # application 전체
logi panopticon kill <client_id> --user user_xyz    # 특정 user만
logi agent revoke <client_id>                       # ALIAS for kill

동작 (계획)

  1. 해당 OauthAccessToken의 모든 refresh token revoke
  2. 기존 access token은 최대 15분 후 자연 만료 (TTL 15분)
  3. panopticon.kill_switch webhook 발사

즉시 차단을 원하면

RP가 매 호출마다 /oauth/introspect 호출 (latency 본인 부담, opt-in). 기본 RP는 15분 지연 수용.


3. HITL 승인 (민감 도구 opt-in) ✓

지정한 도구는 사용자가 logi 앱에서 승인해야만 실행할 수 있습니다. logi 는 승인 결정을 브로커할 뿐 도구 실행을 물리적으로 막는 집행 지점(PEP)은 아닙니다 — 실행을 approved 확인에 바인딩하는 것은 RP 몫입니다.

경로가 바뀌었습니다

이 문서의 2026-05 판은 POST /panopticon/approval/request 를 안내했지만 그 경로는 존재한 적이 없습니다. 실제 경로는 아래의 /panopticon/approvals(복수형) 입니다.

설정 (개발자 콘솔에서 직접)

도구별 opt-in 목록은 oauth_applications.hitl_required_tools 에 저장되며, 개발자 콘솔의 앱 편집 화면에서 한 줄에 하나씩 등록합니다. 이름은 MCP 서버가 보내는 tool_name정확히 같아야 하고 대소문자도 구분합니다.

이름이 어긋나면 두 갈래로 갈립니다 — 어느 쪽도 "승인된 실행"이 아닙니다:

  • 승인 요청을 보냈는데 그 tool_name 이 목록에 없으면 422 tool_not_hitl_required 로 거절됩니다(fail-closed). 승인 레코드도, 푸시도 생기지 않으므로 이 응답을 받고 실행하면 안 됩니다.
  • 애초에 승인 요청을 보내지 않으면 logi 는 결정 브로커이지 집행 지점(PEP)이 아니라서 실행 자체는 막지 못합니다 — 실행을 승인에 바인딩하는 책임은 RP 쪽입니다. 다만 그 호출이 눈에 안 보이는 것은 아닙니다: 등록된 HITL 도구의 성공 trace 가 승인 근거 없이 들어오면 감사 원장에 required_but_missing 정책 위반으로 기록됩니다.

logi panopticon policy --hitl CLI 는 아직 없습니다.

1. 승인 요청

http
POST /panopticon/approvals
Authorization: Bearer pano_pak_...
Content-Type: application/json

{
  "tool_name": "payment.charge",
  "idempotency_key": "<RP 고유 키>",
  "args_digest": "<실행 인자의 SHA-256 hex 64자>",
  "user_sub": "<이 앱의 pairwise sub>",
  "display_title": "결제 승인",
  "display_body": "12,000원을 결제합니다"
}
  • idempotency_key·args_digest·tool_name·user_sub 는 필수입니다.
  • display_title(120자)·display_body(2000자)는 앱 상세 화면에만 표시됩니다. 잠금화면 알림에는 나오지 않습니다. Bearer 토큰·JWT·API 키 같은 시크릿 패턴이 들어 있으면 422 로 거절합니다.
  • user_sub 가 이 앱에 연결된 사용자로 해석되지 않으면 422 user_unresolved (fail-closed — 레코드·푸시·webhook 모두 생성하지 않음).

응답 201(신규) 또는 200(같은 idempotency_key 재사용):

json
{
  "request_uuid": "…",
  "status": "pending",
  "approval_url": "https://api.1pass.dev/approvals/…"
}

같은 idempotency_key 를 다른 (user_sub, tool_name, args_digest) 로 재사용하면 409 idempotency_conflict.

2. 폴링

http
GET /panopticon/approvals/<request_uuid>
Authorization: Bearer pano_pak_...

응답: {"request_uuid":"…","status":"pending|approved|denied|expired|consumed"}

TTL 5분. 만료된 pending 은 조회 시점에 expired 로 전이됩니다.

이미 소비된 승인은 consumed 로 내려옵니다 — 생성·폴링·소비 세 응답이 같은 규칙을 씁니다. 따라서 consume 응답을 못 받았을 때는 폴링으로 1차 판정하세요: consumed 면 앞선 호출이 이미 성공한 것입니다.

approved 는 "재시도 가능"과 동의어가 아닙니다. lazy expire 는 pending 행만 전이시키므로, 승인 후 소비 창(기본 300초)이 지난 행도 폴링에서는 계속 approved 로 보이고 consume 은 409 not_consumable 을 돌려줍니다.

재시도 대상은 consume 요청뿐입니다 — 같은 args_digest 로 consume 을 다시 호출하세요. 도구 실행은 consume 이 200 을 준 뒤에만 합니다. approved 를 보고 도구를 다시 실행하면 앞선 시도가 이미 실행됐을 경우 부작용이 두 번 일어납니다. 409 not_consumable 은 정상 종료 경로(창 만료 또는 이미 소비)로 처리하고 실행하지 마세요.

3. 소비 — 1승인 = 1실행

승인만으로 실행하지 말고, 실행 직전에 그 시점의 인자 해시를 다시 제출해 승인과 바인딩하세요.

http
POST /panopticon/approvals/<request_uuid>/consume
Authorization: Bearer pano_pak_...

{ "args_digest": "<실행 시점 인자의 SHA-256 hex>" }
  • 성공: {"request_uuid":"…","status":"consumed"}
  • 승인 때와 인자가 다르면 409 args_mismatch — 사용자가 본 것과 다른 작업이 실행되는 것을 막습니다.
  • 미승인·이미 소비·소비 창 만료는 409 not_consumable.

사용자 경험

  1. RP 가 승인을 요청하면 사용자 logi 앱에 푸시가 도착합니다. 잠금화면에는 "logi · 도구 실행 승인 요청"과 도구 이름만 노출되고, RP 가 쓴 문구는 앱을 열어 인증한 뒤에만 보입니다.
  2. 사용자가 앱에서 승인/거부합니다.
  3. 결과가 폴링 또는 webhook 으로 RP 에 전달됩니다.

승인이 오지 않는 경로를 반드시 함께 다루세요

1·3단계(푸시 전달, 폴링·webhook)는 동작하고, 2단계의 앱 승인 화면과 approval_url(https://api.1pass.dev/approvals/<request_uuid>) 딥링크도 구현·라우팅돼 있습니다. 다만 다음 경우에는 알림이 사용자에게 닿지 않고 요청은 TTL 5분 뒤 expired 가 됩니다:

  • 스토어에 올라간 앱 버전에 결정 화면이 아직 반영되기 전 — 구버전 앱 사용자는 링크에서 정적 안내 페이지를 만납니다.
  • 푸시 받을 기기가 없음 — 푸시는 푸시 토큰이 있는 활성 기기에만 나갑니다. 대상 기기가 0대면 서버는 전달을 성공으로 처리하므로, 알림이 없었다는 사실은 응답에 드러나지 않습니다.
  • 일시적 전달 실패(APNs/FCM 오류, 토큰 만료).

expired 를 "사용자가 거부함"으로 해석하지 마세요 — 결정이 없었던 것입니다.

에이전트(Claude·Codex·Cursor 등)가 자기 자격증명으로 승인을 요청하는 시나리오는 Agent Approval Gate가 담당합니다. 이 페이지의 HITL 은 RP 서버가 요청자인 경우입니다.


4. Scope Drift Policy

LLM이 등록되지 않은 scope를 요청하는 경우의 처리.

3단계 정책

정책동작추천
block (기본값, 2026-06-10부터)/oauth/authorize에서 미등록 scope 발견 시 400 invalid_scope 반환 (인가 자체 거부, RFC 6749 §4.1.2.1)모든 application (기본)
alertdrift 기록 + 미등록 scope는 버리고 등록된 subset으로 진행 + 관리자 푸시 알림 (30분 cooldown)완화가 필요하되 모니터링 중인 application
log_onlydrift 기록 + 등록된 subset으로 진행opt-in 완화 — 운영자 admin API로만 설정 가능

변경

현재 정책 변경은 운영자 admin API로만 가능합니다. 콘솔 셀프서브 라디오와 logi panopticon policy --drift CLI는 로드맵입니다. 완화가 필요하면 support@1pass.dev로 문의해 주세요.

Scope Drift는 모두 기록됨

정책에 관계없이 ScopeDriftRecord는 모든 drift 이벤트를 적재합니다. 첫 발생 시 scope.drift_detected webhook, escalation 후 scope.drift_unresolved webhook이 발사됩니다 (Webhook 가이드).


사용량과 정책의 관계

베타 동안 구현된 정책은 enforcement만 하고 quota를 차단하지 않습니다. 즉:

  • Rate Limit (rack-attack): 분당 한도 초과 시 throttle (적용됨)
  • Scope Drift block: 미등록 scope 시 invalid_scope 거부 (적용됨, 기본값)
  • 판옵티콘 HITL 승인: 서버 브로커 + 푸시 전달 적용됨 (앱 결정 화면은 구현됐으나 스토어 배포분 반영 전 — 승인이 오지 않는 경로를 함께 다뤄야 함)
  • Soft Kill Switch: 설계 단계 (미적용)

정식 출시 후 추가될 quota 정책 (월 trace 한도, tier별 차등)은 별도 spec에서 다룹니다.

다음

Identity가 제품의 신뢰를 만듭니다.