SettleLab
전체 코스
LESSON 05Account and Agent Payment

세션키와 지출 정책

심화40분근거 1

학습 결과

  • session key의 scope, limit, expiry를 설계한다.
  • agent 자동 결제에서 사용자가 통제권을 잃지 않게 한다.

선행 조건

  • EIP-7702와 EOA 위임

완료 기준

  • session key scope를 정의했다.
  • 사용자 취소 UX를 만들었다.
  • 키 유출 대응을 문서화했다.

세션키와 지출 정책

도입

AI agent나 반복 결제에 master wallet key를 직접 쓰면 안 된다. master key는 계정 전체를 통제하므로 prompt injection, backend compromise, rogue plugin 같은 상황에서 피해 범위가 너무 크다. Session key는 이 문제를 줄이기 위한 제한 권한이다.

좋은 session key policy는 "무엇을 할 수 있는가"보다 "무엇을 할 수 없는가"를 더 명확히 한다. token, chain, merchant, function selector, per-transaction limit, daily limit, valid window, revoke 상태를 모두 제한해야 한다.

학습 목표

  • session key의 scope, limit, expiry를 설계한다.
  • agent 자동 결제에서 사용자가 통제권을 잃지 않게 한다.

개념 설명

상태머신가로 스크롤 · 크게 보기 지원
세션키와 지출 정책 상태머신이 시각화는 account abstraction과 agent payment에서 상태 전이가 어떤 증거와 실패 조건으로 움직이는지를 보여주며, '세션키와 지출 정책'에서 남겨야 할 설계 증거를 좁힌다.
State 1

ScopeDrafted

session key의 scope, limit, expiry를 설계한다.

merchant, selector, token, chain, expiry를 사용자 문구와 정책 값으로 나눈다.
State 2

SpendChecked

서명 권한과 지출 한도가 분리되는가

remaining cap, nonce, merchant allowlist, chain allowlist를 결제 전 검증한다.
State 3

CapNearLimit

paymaster 정책이 설명 가능한가

한도 임박, 비정상 반복 결제, revoke 필요 상태를 dashboard에 올린다.
State 4

ScopeRevoked

세션키와 지출 정책 이해 점검

session key scope를 정의했다.
크게 보기
State 1

ScopeDrafted

session key의 scope, limit, expiry를 설계한다.

merchant, selector, token, chain, expiry를 사용자 문구와 정책 값으로 나눈다.
State 2

SpendChecked

서명 권한과 지출 한도가 분리되는가

remaining cap, nonce, merchant allowlist, chain allowlist를 결제 전 검증한다.
State 3

CapNearLimit

paymaster 정책이 설명 가능한가

한도 임박, 비정상 반복 결제, revoke 필요 상태를 dashboard에 올린다.
State 4

ScopeRevoked

세션키와 지출 정책 이해 점검

session key scope를 정의했다.

session key policy는 지갑, smart account module, backend policy engine, x402 client가 모두 읽을 수 있는 공통 언어여야 한다.

표 자료가로 스크롤 · 크게 보기 지원
필드예시방어하는 위험
sessionKeysub-key addressmaster key 노출 방지
validAfter/validUntil2026-05-15 00:00 to 24:00장기 유출 피해 제한
chainId 또는 CAIP-2eip155:8453wrong-chain 결제 방지
tokenUSDC addresssymbol spoofing 방지
merchantAllowlistapproved API payees악성 endpoint 결제 방지
methodAllowlistcallX402, payInvoice임의 contract call 방지
perTxLimit10 USDC단건 피해 제한
dailyLimit100 USDC누적 피해 제한
nonceDomainapp/payment domainreplay 범위 제한
revokedtrue/false사용자 회수 반영
크게 보기
필드예시방어하는 위험
sessionKeysub-key addressmaster key 노출 방지
validAfter/validUntil2026-05-15 00:00 to 24:00장기 유출 피해 제한
chainId 또는 CAIP-2eip155:8453wrong-chain 결제 방지
tokenUSDC addresssymbol spoofing 방지
merchantAllowlistapproved API payees악성 endpoint 결제 방지
methodAllowlistcallX402, payInvoice임의 contract call 방지
perTxLimit10 USDC단건 피해 제한
dailyLimit100 USDC누적 피해 제한
nonceDomainapp/payment domainreplay 범위 제한
revokedtrue/false사용자 회수 반영

session key 상태도 명확해야 한다.

흐름도가로 스크롤 · 크게 보기 지원
강의 흐름도상태, 책임, 검증 지점을 순서대로 읽기 위한 다이어그램이다.
크게 보기

정책은 화면에만 있으면 안 된다. 실제 결제 요청이 들어올 때마다 wallet validation, backend policy engine, spend ledger가 같은 결론을 내야 한다. 한쪽만 통과하면 공격자가 가장 약한 지점을 우회 경로로 사용한다.

흐름도가로 스크롤 · 크게 보기 지원
강의 흐름도상태, 책임, 검증 지점을 순서대로 읽기 위한 다이어그램이다.
크게 보기

이 흐름에서 Policy EngineSmart Account는 서로를 대체하지 않는다. backend는 UX, rate limit, merchant policy를 빠르게 판단하고, wallet/module은 최종 onchain 권한 경계를 강제한다. 둘 중 하나라도 느슨하면 session key는 제한 권한이 아니라 자동 결제용 hot key가 된다.

코드로 확인하기

session key는 "자동 결제 허용"이 아니라 제한된 대리 서명자다. 코드에서는 session key가 할 수 있는 일과 할 수 없는 일을 먼저 표현해야 한다.

컨트랙트session key 정책 검증

CODE SURFACEsolidity
struct SessionPolicy {    address key;    address token;    address merchant;    uint256 maxPerPayment;    uint256 maxTotal;    uint64 validUntil;}function validateSessionPayment(    SessionPolicy memory policy,    uint256 amount,    address merchant,    bytes4 selector) internal view {    if (block.timestamp > policy.validUntil) revert SessionExpired();    if (merchant != policy.merchant) revert MerchantNotAllowed();    if (selector != Checkout.pay.selector) revert SelectorNotAllowed(selector);    if (amount > policy.maxPerPayment) revert PaymentTooLarge(amount);    if (spent[policy.key] + amount > policy.maxTotal) revert SessionBudgetExceeded();}

session key 정책은 selector와 merchant를 함께 묶어야 한다. 금액 제한만 두면 같은 token으로 다른 contract에 결제하는 공격을 설명하기 어렵다.

클라이언트session scope를 사용자가 읽을 수 있게 만들기

CODE SURFACEtypescript
type SessionScope = {  merchantName: string;  merchantAddress: `0x${string}`;  tokenSymbol: "USDC";  maxPerPayment: string;  totalBudget: string;  expiresAt: string;};function summarizeSessionScope(scope: SessionScope) {  return [    `${scope.merchantName}에게만 결제`,    `한 번에 최대 ${scope.maxPerPayment} ${scope.tokenSymbol}`,    `전체 예산 ${scope.totalBudget} ${scope.tokenSymbol}`,    `${scope.expiresAt} 이후 자동 만료`  ];}

이 설명이 화면에 없으면 사용자는 agent 결제와 무제한 지출 권한을 구분하지 못한다. 코드와 UI 문구가 같은 정책을 말해야 한다.

강의 포인트

표 자료가로 스크롤 · 크게 보기 지원
관점확인할 질문증거로 남길 것
scopetoken, chain, merchant, method가 좁게 제한됐는가policy schema
limitperTx, daily, monthly cap과 reset rule이 있는가spend accounting table
expiryvalidAfter/validUntil과 renewal UX가 있는가lifecycle diagram
revocation사용자가 즉시 끌 수 있고 UI에서 확인할 수 있는가revoke flow
incidentkey 유출 시 남은 payload가 실패하는가compromise runbook
크게 보기
관점확인할 질문증거로 남길 것
scopetoken, chain, merchant, method가 좁게 제한됐는가policy schema
limitperTx, daily, monthly cap과 reset rule이 있는가spend accounting table
expiryvalidAfter/validUntil과 renewal UX가 있는가lifecycle diagram
revocation사용자가 즉시 끌 수 있고 UI에서 확인할 수 있는가revoke flow
incidentkey 유출 시 남은 payload가 실패하는가compromise runbook

운영 지표도 설계에 포함한다. session key는 "사용자가 허용했다"는 사실보다 "허용된 범위 안에서만 계속 쓰이고 있는가"를 관찰해야 한다.

표 자료가로 스크롤 · 크게 보기 지원
지표정상 범위이상 신호
active sessions per user사용자가 인지 가능한 소수알 수 없는 session이 갑자기 증가
rejected payments일부 policy mismatch특정 merchant에서 반복 거절
cap usage velocity사용 패턴과 유사짧은 시간에 daily cap 소진
revocation latency즉시 또는 다음 block 내 반영revoke 후 payment가 계속 승인
stale sessions만료 직후 자동 정리오래된 session이 UI에 남음
크게 보기
지표정상 범위이상 신호
active sessions per user사용자가 인지 가능한 소수알 수 없는 session이 갑자기 증가
rejected payments일부 policy mismatch특정 merchant에서 반복 거절
cap usage velocity사용 패턴과 유사짧은 시간에 daily cap 소진
revocation latency즉시 또는 다음 block 내 반영revoke 후 payment가 계속 승인
stale sessions만료 직후 자동 정리오래된 session이 UI에 남음

실무 예시

agent subscription 결제를 위한 session key를 설계해보자. 사용자는 market data API에 하루 20 USDC까지 자동 결제를 허용한다.

표 자료가로 스크롤 · 크게 보기 지원
정책
tokenBase USDC
merchantmarket-data.example payee only
functionx402 payment 또는 payInvoice only
per request1 USDC
daily cap20 USDC
valid window24 hours
receiptrequired
revokedashboard에서 즉시 revoke
크게 보기
정책
tokenBase USDC
merchantmarket-data.example payee only
functionx402 payment 또는 payInvoice only
per request1 USDC
daily cap20 USDC
valid window24 hours
receiptrequired
revokedashboard에서 즉시 revoke

이 정책이 있으면 agent가 비싼 endpoint를 반복 호출하도록 유도되어도 per request cap과 daily cap이 피해를 제한한다.

사용자 화면에는 기술 세부사항을 모두 노출하지 않되, 취소 판단에 필요한 정보는 숨기지 않는다.

표 자료가로 스크롤 · 크게 보기 지원
UI 영역보여줄 내용이유
활성 세션merchant, token, 남은 한도, 만료 시각사용자가 현재 권한을 이해한다
최근 결제request id, endpoint, 금액, receipt오남용 여부를 확인한다
취소 버튼즉시 revoke, pending request 차단피해 확산을 막는다
경고 상태cap 초과, 알 수 없는 merchant, 만료 임박자동 결제 실패를 사용자가 해석한다
크게 보기
UI 영역보여줄 내용이유
활성 세션merchant, token, 남은 한도, 만료 시각사용자가 현재 권한을 이해한다
최근 결제request id, endpoint, 금액, receipt오남용 여부를 확인한다
취소 버튼즉시 revoke, pending request 차단피해 확산을 막는다
경고 상태cap 초과, 알 수 없는 merchant, 만료 임박자동 결제 실패를 사용자가 해석한다

capstone에서는 이 UI 상태를 단순 mock으로만 두지 않는다. session key policy, spend ledger, revoke action, payment receipt가 같은 identifier를 공유해야 한다.

흔한 오해와 실패 시나리오

표 자료가로 스크롤 · 크게 보기 지원
오해실제로 확인할 것
session key가 있으면 agent 결제가 안전하다고 본다.session key scope가 넓으면 master key 대신 다른 hot key를 만든 것뿐이다.
expiry만 있으면 충분하다고 본다.merchant, method, token, amount limit이 함께 있어야 한다.
revoke를 backend flag로만 처리한다.smart account 또는 module validation에서도 revoked 상태가 반영되어야 한다.
dailyLimit만 있으면 prompt injection을 막는다고 본다.per request cap과 endpoint allowlist가 같이 필요하다.
사용자 dashboard를 나중에 만든다고 본다.사용자가 active session과 남은 한도를 볼 수 있어야 통제권을 잃지 않는다.
크게 보기
오해실제로 확인할 것
session key가 있으면 agent 결제가 안전하다고 본다.session key scope가 넓으면 master key 대신 다른 hot key를 만든 것뿐이다.
expiry만 있으면 충분하다고 본다.merchant, method, token, amount limit이 함께 있어야 한다.
revoke를 backend flag로만 처리한다.smart account 또는 module validation에서도 revoked 상태가 반영되어야 한다.
dailyLimit만 있으면 prompt injection을 막는다고 본다.per request cap과 endpoint allowlist가 같이 필요하다.
사용자 dashboard를 나중에 만든다고 본다.사용자가 active session과 남은 한도를 볼 수 있어야 통제권을 잃지 않는다.

실습 과제

  1. 세션키와 지출 정책 이해 점검: sessionKey, chainId, token, merchantAllowlist, methodAllowlist, perTxLimit, dailyLimit, validUntil, revoked를 포함한 policy schema를 작성한다.
  2. agent subscription 설계: 유료 API를 하루 20 USDC 한도로 쓰는 agent payment flow와 UI 상태를 만든다.
  3. 키 유출 대응 문서화: session key leak을 발견했을 때 revoke, pending payload invalidation, receipt audit, user notification 절차를 작성한다.
  4. cap reset 정책 작성: dailyLimit reset 기준, timezone, partial failed payment 처리 기준을 정한다.

완료 기준

  1. session key scope를 정의했다.
  2. 사용자 취소 UX를 만들었다.
  3. 키 유출 대응을 문서화했다.

근거 자료

  • 세션키 지출정책: 05-계정추상화-에이전트결제/05-세션키-지출정책.md
Final checkpoint

읽기를 마쳤다면 여기서 기록한다

아래 버튼은 읽기 진도를 저장한다. 체크리스트, 과제, 랩 산출물은 위 Workbook에서 따로 관리한다.

  • session key scope를 정의했다.
  • 사용자 취소 UX를 만들었다.
  • 키 유출 대응을 문서화했다.

학습 자료 근거

세션키 지출정책
이 LMS 레슨의 개념, 예시, 과제 구성을 잡는 데 사용한 근거 문서.
내부 참고 문서