You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
수신자 본인 확인 캐시가 발신자 구분 없이 전역 저장 — 첫 인증 후 이메일 관문 무력화 #597
DeliveryVerificationFlowViewModel 이 이 값을 보고 Intro 화면을 건너뛰어 마스터 키 단계로 바로 점프합니다(ReceiverNavGraph.kt:97).
재현
발신자 A 가 내 이메일로 나를 수신자 등록 → 앱에서 이메일 인증 통과 → identity_verified = true (DataStore 영구)
발신자 B 의 마스터 키를 입수 → 열람 신청 진입 시 이메일 인증 단계가 건너뛰어짐
B 가 나를 수신자로 등록한 적이 없어도 마스터 키 검증 단계로 바로 들어감
이메일 인증의 역할이 "마스터 키만으로는 열 수 없다" 는 2차 확인인데, 전역 값이라 첫 1회로 무력화됩니다. markVerified() 호출 시점에 흐름 ViewModel 이 senderId 를 이미 보유하고 있어 키를 발신자별로 나누는 것으로 해결됩니다.
📌 Child Issue(Optional)
No response
📍 Note (Optional)
BE 쪽 선행 건이 있습니다 — Afternote-BE #74(/receiver-auth/email/verify 응답에서 accessCode 삭제). 07-29 release 실측 기준 아직 마스터 키를 그대로 내려주고 있어서, 그게 남아 있는 동안은 이메일 인증만 통과하면 마스터 키를 서버가 알려주는 구조입니다. 두 건이 모두 정리돼야 2단 확인이 성립합니다.
키를 identity_verified_<senderId> 로 바꾸면 기존 저장값은 무효가 됩니다. 이미 인증한 사용자가 한 번 더 인증하게 되는데, 지금 발신자 카드가 in-memory 라 앱 재시작 시 어차피 재등록이 필요해 실사용 영향은 없습니다.
캐시를 도입한 커밋 8a9ffa7a(2026-05-24) 시점에 이메일 인증은 IdentityEmailVerificationStub 이었습니다 — 클래스 KDoc 이 "백엔드 미구현 단계라 시뮬레이션한다", 고정 코드 000000, 네트워크 호출 0회. 서버 대조가 없으니 "이 단계를 통과했다" 는 플래그 하나로 충분했고, 발신자별이라는 개념이 필요 없었습니다. 그 커밋의 목적도 "앱 재시작 후에도 본인 확인 여부 유지"(영속화)뿐이었습니다.
이후 #407 로 실 API(receiver-auth/email/*)가 붙으면서 이 단계의 의미가 "그 발신자가 등록해 둔 수신자 본인인가" 로 바뀌었는데, 캐시 구조는 따라가지 않았습니다.
참고로 노션 IA 의 수신자 트리에는 "보안링크 접속 → 마스터키 입력" 만 있고 이메일 인증 단계 자체가 없습니다(https://app.notion.com/p/IA-2bd0982937878162a685c52e87d517cf). 이 단계는 IA 이후에 추가된 것이라 기획 문서로는 범위를 확인할 수 없고, 지금 구현된 실 API 의 계약(발신자가 등록한 수신자 이메일로 코드 발송, 미등록이면 404/1901)에 맞추면 발신자별이 맞습니다.
changed the title [-]fix(afternote): 수신자 본인 확인 캐시가 발신자 구분 없이 전역 저장 — 첫 인증 후 이메일 관문 무력화[/-][+]수신자 본인 확인 캐시가 발신자 구분 없이 전역 저장 — 첫 인증 후 이메일 관문 무력화[/+]on Aug 28, 2026
FE 몫(본인 확인 캐시의 발신자별 키 분리)은 PR #1371 로 반영됐다. 이 이슈는 열린 Afternote-BE#74(verify 응답의 accessCode 삭제)가 닫혀 2단 확인이 성립할 때 닫는다 — 머지 가드(blocked_by 검사)에 따라 PR 은 Refs 로만 연결.
소비처도 발신자별로 갈렸다 — DeliveryVerificationFlowViewModel:52 가 isVerified(senderId) 를, IdentityVerificationViewModel:105 가 markVerified(senderId) 를 부른다. 전역 boolean 은 없다.
커밋 2건이 순서대로 들어갔다
커밋
내용
316dd3656
본인 확인 캐시를 발신자별 키로 격리
14a3e058a
그 캐시를 DataStore 에서 프로세스 수명 in-memory 로 되돌림
두 번째 커밋은 재현 절차 1번의 전제(«identity_verified = true DataStore 영구»)까지 없앤다 — 키인 senderId 가 SenderRegistry 의 프로세스 수명 UUID 라 디스크에 남겨도 다시는 조회되지 않고 죽은 키만 쌓이기 때문이다. 구 릴리스가 남긴 전역 identity_verified 잔존값도 이 구현이 디스크를 읽지 않으므로 어떤 발신자의 관문도 열 수 없다.
남는 갈래는 이 이슈 밖이다 — 프로세스를 넘는 발신자 식별자(BE 발급 sender id 또는 마스터 키의 비가역 파생값)가 생기면 영속을 되살릴지 다시 판단하게 되는데, 그 식별자는 #607(record-boxes 연동)이 만든다. 참고란의 BE #74 도 그쪽 전제다.
Activity
OnlyReadOneBook commentedon Jul 29, 2026
경위 — stub 시절 구조가 남은 것
의도한 설계가 아니라 이력의 산물입니다.
캐시를 도입한 커밋
8a9ffa7a(2026-05-24) 시점에 이메일 인증은IdentityEmailVerificationStub이었습니다 — 클래스 KDoc 이 "백엔드 미구현 단계라 시뮬레이션한다", 고정 코드000000, 네트워크 호출 0회. 서버 대조가 없으니 "이 단계를 통과했다" 는 플래그 하나로 충분했고, 발신자별이라는 개념이 필요 없었습니다. 그 커밋의 목적도 "앱 재시작 후에도 본인 확인 여부 유지"(영속화)뿐이었습니다.이후 #407 로 실 API(
receiver-auth/email/*)가 붙으면서 이 단계의 의미가 "그 발신자가 등록해 둔 수신자 본인인가" 로 바뀌었는데, 캐시 구조는 따라가지 않았습니다.참고로 노션 IA 의 수신자 트리에는 "보안링크 접속 → 마스터키 입력" 만 있고 이메일 인증 단계 자체가 없습니다(https://app.notion.com/p/IA-2bd0982937878162a685c52e87d517cf). 이 단계는 IA 이후에 추가된 것이라 기획 문서로는 범위를 확인할 수 없고, 지금 구현된 실 API 의 계약(발신자가 등록한 수신자 이메일로 코드 발송, 미등록이면 404/1901)에 맞추면 발신자별이 맞습니다.
[-]fix(afternote): 수신자 본인 확인 캐시가 발신자 구분 없이 전역 저장 — 첫 인증 후 이메일 관문 무력화[/-][+]수신자 본인 확인 캐시가 발신자 구분 없이 전역 저장 — 첫 인증 후 이메일 관문 무력화[/+]OnlyReadOneBook commentedon Aug 28, 2026
FE 몫(본인 확인 캐시의 발신자별 키 분리)은 PR #1371 로 반영됐다. 이 이슈는 열린 Afternote-BE#74(verify 응답의 accessCode 삭제)가 닫혀 2단 확인이 성립할 때 닫는다 — 머지 가드(blocked_by 검사)에 따라 PR 은 Refs 로만 연결.
fix: 본인 확인 캐시를 프로세스 수명 in-memory 로 되돌린다 (#597)
OnlyReadOneBook commentedon Aug 29, 2026
해소 확인 — PR #1371 (머지됨)
origin/develop실측 결과 이 이슈가 지적한 구조가 남아 있지 않다.Closes가 아니라 참조로 걸려 자동 종료되지 않은 것으로 보인다.이슈가 지적한 것
현행 (
feature/receiver/data/.../IdentityVerificationRepositoryImpl.kt)소비처도 발신자별로 갈렸다 —
DeliveryVerificationFlowViewModel:52가isVerified(senderId)를,IdentityVerificationViewModel:105가markVerified(senderId)를 부른다. 전역 boolean 은 없다.커밋 2건이 순서대로 들어갔다
316dd365614a3e058a두 번째 커밋은 재현 절차 1번의 전제(«
identity_verified = trueDataStore 영구»)까지 없앤다 — 키인senderId가SenderRegistry의 프로세스 수명 UUID 라 디스크에 남겨도 다시는 조회되지 않고 죽은 키만 쌓이기 때문이다. 구 릴리스가 남긴 전역identity_verified잔존값도 이 구현이 디스크를 읽지 않으므로 어떤 발신자의 관문도 열 수 없다.남는 갈래는 이 이슈 밖이다 — 프로세스를 넘는 발신자 식별자(BE 발급 sender id 또는 마스터 키의 비가역 파생값)가 생기면 영속을 되살릴지 다시 판단하게 되는데, 그 식별자는 #607(record-boxes 연동)이 만든다. 참고란의 BE #74 도 그쪽 전제다.
해소되었으므로 닫는다.