# 동의 모델

## 기본 차단 (deny-by-default)

점수·등급·사유코드는 사용자가 앱에서 **특정 기관 × 특정 목적**에 명시적으로 동의한 경우에만 반환됩니다.

- 동의는 기관(clientId) + 목적(purpose) 단위 — 다른 목적으로 재사용 불가
- 사용자는 언제든 철회 가능, 철회 즉시 거부 전환
- 동의에는 만료 시각이 있으며 만료 후 재동의 필요
- 동의 없음·철회·만료·주체 없음은 FI 관점에서 구분 불가하게 거부(배치는 단일 DENIED, 타이밍 균일화)

## 파트너 전용 익명 ID (pairwise 식별자)

- 같은 사용자라도 기관마다 다른 `pairwiseSub` — 기관 간 결합(cross-linking) 불가
- 내부 식별자(civilId/userId)·실명·연락처는 API 표면에 노출되지 않음
- 파트너 로그인(SSO) 동의 과정에서 발급된 값을 그대로 사용

## 데이터 카테고리

동의 상태 응답의 `dataCategories`(CSV 문자열)로 확인합니다.

| 카테고리 | 제공 데이터 | 기본 포함 |
|---|---|---|
| `score` | 점수(0~850) | 기본 |
| `tier` | 등급 | 기본 |
| `reason-codes` | 사유코드(최대 4건) | 기본 |
| `contributions` | 피처별 기여 상세 | 선택 |
| `history` | 점수 이력(`GET /fi/score/history`) | 선택 |
| `monitoring` | 모니터링 웹훅(`score.updated`·`tier.changed`) | 선택 |

`consent.revoked` 웹훅은 카테고리 무관 발송 — 철회 사실을 알아야 데이터 보관을 중단할 수 있기 때문.
철회 후에는 이 이벤트 외 어떤 이벤트도 발송되지 않습니다.

## 동의 흐름

1. FI가 `POST /fi/consent/requests` → 사용자 앱 인앱 알림
2. 사용자가 목적·카테고리를 확인하고 승인/거절
3. 승인 시 동의 영수증 생성 — `GET /fi/consent/{consentReceiptId}`로 상태 확인
4. 이후 조회 가능 — 매 조회가 동의 검사를 통과해야 함
5. 철회 시 즉시 거부 전환 + `consent.revoked` 웹훅

## 사용자에게 보이는 것

모든 조회는 접근로그에 기록되며, 사용자는 앱에서 어느 기관이 언제 무슨 목적으로 조회했는지 열람할 수
있습니다. 접근로그는 해시체인으로 연결되어 사후 변조를 탐지할 수 있습니다([compliance.md](compliance.md)).
