finance.crowny.org 초대 서비스 하드닝 — 완료
개요
초대 바이럴 서비스 감사가 잡아낸 리스크 3건을 근본 수정. 울트라 워크플로우 6에이전트(설계2→구축2→수리→검증2) + 직접 캡 가드 추가. 독립 재검증 통과.
1. 회전 WAL 영속화 (재시작 복원 + 재지급 방지)
- WAL 레코드 4종(append-only, 해시만 저장): P(본인폰등록) / S(연락처 sync) / J(가입+보상 원자결합 paid=0/1) / L(원장). 파이프 구분, 줄이스케이프.
- 회전 파트:
data/invite-wal.pN.dat 각 <12KB(WAL_PART_MAX, STR_MAX_LEN 16KB 안전여유). invite-wal.meta.dat = part|byteoffset|seq. 임계 초과 시 자동 파트 회전.
- 부팅 replay:
초대로드()가 p0,p1,… 순차 읽기(없는 파일 글자수 가드) → 초대DB+원장+멱등마커(_joined_/_pair_/_SLOT_보상/_self_) 결정론적 재구성. 서버 init(접수로드 직후) 연결.
- 재지급 0: 보상 발생 시에만 J(paid=1)/L 기록 → replay가 정확히 1회 재현. 재시작 후 동일 가입 재유입 시 _joined_ 적중 → 0맘.
독립 검증 (실측)
sync itZ(selfPhone, 큐) → join 큐 → itZ +1맘
백엔드 kill → 재기동 → "[load] 초대WAL 82레코드 replay" → rewards/itZ momEarned=1 (영속!)
re-join 큐 → firstJoin:false, rewarded:[], skipped:already_joined → 재지급 0
WAL 회전: p0/p1/p2 각 <4KB, 78~83 레코드 cross-part replay 정상
PII: WAL 평문 폰 0건(SHA256 해시+마스킹명만)
2. 자가가입 보상 차단 (selfPhone 필수화)
/api/invite/sync에 selfPhone 필수(누락 <4자 → HTTP 400 SELF_PHONE_REQUIRED, 동기화 미수행).
본인폰등록() 강화: 무효 -1, 같은 user 다른 해시 -2(immutable), _self_<user>+_owner_<해시> 세팅 후 WAL P 기록.
- 가입처리 보상 게이트: hash(가입폰)==
_self_<등록자> → 자가=1 스킵, _owner_<해시>==등록자 → 순환차단, _self_ 미등록 → 미검증=1 보상보류. 보상 = 이미보상0 AND firstJoin1 AND 자가0 AND 미검증0. skipped[{registrant,reason}] 응답.
- 본인 번호를 contact로 등록도 거부(연락처등록 r==-2).
- 프론트: 동기화 카드에 "내 전화번호(본인 인증용)" 필드 추가, sync 바디 selfPhone 포함(localStorage cfInviteSelfPhone).
3. 연락처 캡 가드 (대량 sync 크래시 방지 — 직접 추가)
- 검증이 발견: 200건 단일 sync가 16KB/누적틱 한계로 백엔드 silent death(~75건 후).
연락처동기화()에 최대 30건/요청 처리 상한. 초과 시 capped:1+maxPerSync:30 반환 → 클라이언트 분할 재전송 유도.
- 검증: 40건 sync → registered:30, capped:1, 백엔드 생존(health ok), 회귀 정상.
관련 파일
- 백엔드: /Users/ef/crowny-finance/src/크라우니파이낸스.한선 (초대로드/walAppend/walReplay, 본인폰등록 강화, 가입처리 게이트, 연락처동기화 캡). 3.07MB toau, compile exit 0.
- 프론트: web/assets/chat.js (selfPhone 필드), chat.css
- 데이터: data/invite-wal.pN.dat + invite-wal.meta.dat (회전 WAL)
- 실행: 백엔드 :9750(/tmp/finance2.toau), 프록시 :9754. 단일 인스턴스.
운영 메모
- 검증 중 watchdog(pid 1884)가 /tmp/crowny-finance.toau로 중복 백엔드를 :9750에 띄워 테스트 오염 → watchdog SERVICES에 finance 직접 항목은 없으나 monitor(9743) 관리 중. 현재 단일 백엔드 확인.
- 남은 한계(설계상): 인메모리+WAL 하이브리드라 WAL이 단일 진실원. WAL 파일 손상 시 복원 불가 → 주기적 백업 권장. 대규모(수천 사용자)는 파트 수 증가로 부팅 replay 지연 가능 → 스냅샷 compaction 후속.