E2EE P1 — 켜기·기기 승인(지문 대조)·복구 코드·재봉인·세대 게이트 - #328
Merged
Conversation
권고안 승인분(E2EE-DESIGN.md §6~§7)의 단계 1 실행 코드. DEK 보유가 곧 스위치(디스크 사실 파생). - 켜기(enable): 이 기기가 DEK 생성 → 자기 랩(wrapped_deks)·복구 랩(recovery_wraps) 서버 기록(전부 암호문) → 성공 후에만 로컬 DEK 확정(반쪽 활성 방지) → 전 회사 재봉인 마커 + nudge. 복구 코드는 1회만 반환·서버 무저장. 플랜 게이트(Pro·체험 — free는 재봉인 push가 RLS에 막혀 "켰는데 암호화 안 됨"이 되므로 사전 정직 차단, #325 HIGH-2 원칙). - 기기 승인(approve): DEK 보유 기기가 대상 공개키로 랩해 wrapped_deks에 기록. 사용자는 양 화면의 지문(SAS) 대조 후 승인 — 서버의 공개키 바꿔치기는 지문 불일치로 드러난다. 새 기기는 claim (자기 랩 회수·cycle 60초 자동 시도)으로 잠김 해제. 복구 코드 폴백(recover) 포함. - v3 전량 봉인: DEK 보유 기기의 push는 파일·매니페스트 전부 v3. **매니페스트 봉인이 곧 게이트** — 열쇠 없는 기기(구버전 포함)는 매니페스트 개봉이 보류로 떨어져 회사 동기화가 통째로 안전 정지 (파일 단위 오염·오삭제 원천 불가, 기존 "매니페스트 읽기 실패 보류" 경로 재사용). - 재봉인(reseal): 켠 직후 1회, 무변경 파일도 blob을 v3로 되덮음(메타·base 불변 — 타 기기 diff 무영향). WS_ROOT 마커(.e2ee-reseal.json, 셸 금고 등재)로 회사별 재시도. - 기기 제거(revoke): 랩·공개키 행 삭제(재등록 가능). DEK 회전은 후속 — UI가 사실 그대로 고지. pubkey 최초 등록 후 불변(ignoreDuplicates — §10.5 하이재킹 차단), keyMismatch 정직 표기. - UI: 설정 E2EE 카드(꺼짐/잠김/켜짐 3상태, 구버전 확인 체크, 복구 코드 1회 모달, 지문 대조 안내). i18n ko/en 전량. - 테스트 6종(복구 왕복·관용 입력·지문·claim·v3 전환·잠김 보류·재봉인) + 변이 red 2종(sealFor dek 분기·reseal 분기). 전체 스위트 fail 0 · next build 통과. 라이브(상주) 검증은 배포 후: 카드 렌더·GET 계약 확인 — 실제 켜기는 전 기기 업데이트 후 유건 판단(구버전 혼재 시 그 기기 동기화가 잠김 상태로 정지). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- HIGH-1(실증됨): 열쇠 없는 기기의 정상 사이클이 재읽기에서 v3 매니페스트를 만나도 catch로 삼키고
자기 평문 매니페스트를 되써 게이트를 다운그레이드했다. 재읽기를 두 단계로 분리 — 네트워크 실패는
기존 관용, **받았는데 열 수 없는 봉투 세대(isEnvelopeGeneration)는 사이클 전체 보류**(다음 사이클
초기 읽기가 정식 잠김 경로로 수렴). 회귀 테스트 = 검수 재현 시나리오 그대로(초기 읽기 1회 평문·
재읽기 v3 → 보류 + 원격 v3 유지), 게이트 제거 변이 red 실증.
- HIGH-2: 기기 제거 고지가 사실과 반대("새 동기화를 열 수 없게 됩니다")였다 — 행 삭제는 "새 열쇠
미배포"일 뿐, 이미 열쇠 받은 기기는 로컬 열쇠+세션이 살아있는 한 계속 연다. 문구를 사실대로
정정하고 실효 조치(세션 차단·비밀번호 변경)를 안내. 제거·승인에 확인 모달(승인 = 지문 대조 확인).
- MEDIUM-1: enable 반쪽 잔재(자기 랩만 기록 후 복구 랩 실패)가 "다른 기기에서 켜짐" 오판으로 영구
교착 — 판정에서 자기 행 제외 + 자기 랩 존재 시 openDekWrap로 같은 DEK 이어가기(재시도 = 자가 치유).
- MEDIUM-2: 재봉인 완결을 파일 실패 0으로 조건화 — 종전엔 개별 push 실패 파일이 영구 구세대로
남았다(마커 잔존 → 회사째 재시도).
- LOW: recover 5초 스로틀(scrypt CPU 증폭 방지), TRIAL_DAYS 상수 사용(하드코딩 드리프트 제거).
테스트 7/7(세대 게이트 신설 포함) · 전체 스위트 fail 0 · next build 통과.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
목적
E2EE 단계 1(옵트인) — P0(#327)의 기기 키쌍·v3 봉투 위에서, 계정이 실제로 "본인만 여는" 상태로 전환하는 실행 코드. 설계 정본 E2EE-DESIGN.md §6~§7.
변경
검증
롤아웃·미검증(정직 표기)
🤖 Generated with Claude Code