iykyka/mobile
Claude a8c7b98922
스팸/도배 감지 최소 버전(2.7-C) 구현: 대화방 단위 자동 응대 일시중단 + 재개
PRD.md §4 엣지케이스가 "안전 관련이라 v1 최소 버전 필요"로 명시한 항목(P0)인데
관련 로직이 0건이었던 마지막 콘텐츠 갭(roadmap.md §2.7-C, deploy-checklist.md
N4-C3a/b)을 채운다. Track C(콘텐츠 갭) A/B/C 전체 완료.

- core-backend/flood_detect.go(신규): floodMessageThreshold=5건 /
  floodWindow=2분 상수 + floodDetected()/floodReason(). 안전을 위해 반드시
  있어야 하는 기술적 최소값이라 명시적으로 placeholder로 남기고 구현했다 —
  roadmap.md §3의 "PoC 결과가 있어야 정할 수 있는 것"(자율성 기본값 등 UX
  기본값)과는 성격이 다름. 카운트는 대화방 내 sender_id != 소유자인 메시지만
  집계(트윈 자동발송·소유자 본인 발송은 소유자 ID로 남으므로 자동 제외).
- core-backend/main.go: POST /conversations/:id/messages 하드게이트에
  peer-veto → 그룹 대화 차단 다음, 에스컬레이션 체크 이전 지점으로 추가 —
  트윈 자동발송 시도가 전부 지나가는 동일한 우회 불가 지점. 이미
  TwinDisabledByFlood가 켜져 있으면 재계산 없이 즉시 차단(중복 로그/쿼리
  방지). 새로 임계치를 넘기면 대화방을 영구 차단하고 EscalationLog 기록 +
  notifyUser 푸시.
- core-backend/models.go: Conversation.TwinDisabledByFlood 필드 추가.
  TwinDisabledByPeer(거부권, 사람의 일방적 선택 — v1엔 되돌리기 API 없음)와
  달리 이건 시스템이 자동으로 취하는 조치라서 AGENTS.md "every automatic
  action needs post-hoc notification + one-tap undo"가 그대로 적용됨 —
  POST /conversations/:id/flood-reset로 되돌릴 수 있게 별도 필드로 분리.
- core-backend/a1_a2_routes.go: GET /conversations 응답에
  twin_disabled_by_flood 추가(twin_disabled_by_peer와 동일한 자리).
- core-backend/flood_detect_test.go(신규): 임계치 경계값(정확히 N건은
  통과, N+1건은 차단), 사람 발송은 게이트 안 걸림, 윈도우 밖 과거 메시지는
  집계 제외, flood-reset으로 재개, 존재하지 않는 대화방 404 — 5개 테스트.
- mobile/lib/models/models.dart, services/api_client.dart: 모델·API
  클라이언트에 twinDisabledByFlood/resetFlood() 추가.
- mobile/lib/screens/conversation_list_screen.dart: 대화 목록에 도배 차단
  배지(거부권과 같은 자리, 다른 아이콘/문구).
- mobile/lib/screens/chat_screen.dart: 채팅방을 열면(목록에서 넘어온 초기
  상태) 또는 발송 시도가 다시 차단되면 배너에 "자동응대 재개" 버튼을 보여줌
  — one-tap undo. 새 알림 메커니즘을 만들지 않고 기존 EscalationLog/
  InboxScreen을 그대로 재사용.
- mobile/test/models_test.dart: twin_disabled_by_flood 파싱 테스트 추가.
- docs/roadmap.md §2.7-C, docs/deploy-checklist.md N4-C3a/b·Track C 요약·
  "바로 다음 5개"를 완료로 갱신.

테스트: go test ./... 51/51, python3 -m pytest tests/ -q 47/47,
flutter analyze 클린 + flutter test 5/5 모두 통과.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
2026-08-03 05:12:29 +00:00
..
android feat(n4): wire FCM token path and document Master secrets 2026-07-31 04:51:57 +00:00
lib 스팸/도배 감지 최소 버전(2.7-C) 구현: 대화방 단위 자동 응대 일시중단 + 재개 2026-08-03 05:12:29 +00:00
test 스팸/도배 감지 최소 버전(2.7-C) 구현: 대화방 단위 자동 응대 일시중단 + 재개 2026-08-03 05:12:29 +00:00
web 제품명 변경(분신→와카뷰) + 소프트 그라디언트/글래스모피즘 UI + 브랜드 로딩 화면 2026-07-31 01:15:42 +00:00
.gitignore Add Flutter mobile client skeleton and defer human PoC to last 2026-07-30 04:16:41 +00:00
.metadata fix Flutter Web/Chrome compile by stubbing SQLCipher DB 2026-07-30 07:05:31 +00:00
Dockerfile feat(deploy): Docker Compose stack for msn.iykyka.com (N2-B) 2026-07-31 02:26:40 +00:00
Dockerfile.prebuilt feat(deploy): Docker Compose stack for msn.iykyka.com (N2-B) 2026-07-31 02:26:40 +00:00
README.md feat(n4): wire FCM token path and document Master secrets 2026-07-31 04:51:57 +00:00
analysis_options.yaml Add Flutter mobile client skeleton and defer human PoC to last 2026-07-30 04:16:41 +00:00
pubspec.lock Merge remote-tracking branch 'origin/main' 2026-07-31 08:23:28 +00:00
pubspec.yaml feat(n4): wire FCM token path and document Master secrets 2026-07-31 04:51:57 +00:00

README.md

와카뷰 mobile (Flutter)

Phase 1 클라이언트 (docs/roadmap.md §2.3 / A3). v1은 Android 빌드만 대상으로 한다 (docs/tech-design.md §8).

지금 있는 것

  • 초대 코드 가입 (POST /auth/signup) + Bearer 세션
  • 말투 샘플 온보딩(기기 로컬 저장; 최종 카피는 PoC 이후)
  • 대화방 목록/생성 (GET/POST /conversations) — 수동 ID 입력 제거
  • 연락처 CRUD + 대화 시작 (/users/:id/contacts)
  • 채팅 히스토리 로드 + WebSocket 수신
  • 와카뷰 초안 / L1 승인(수정·버리기·재초안·승인 발송)
  • 와카뷰 뱃지 · 거부권 · 되돌리기
  • 사후 알림 함 (GET /users/:id/escalation-logs)
  • 자율성 L0~L2 + 화이트리스트 CRUD UI

실행

# core-backend + ai-service 가 떠 있어야 실제 호출이 된다
cd mobile
flutter pub get

# Android 에뮬레이터 → 호스트의 core-backend(기본 8080)
flutter run --dart-define=CORE_API_BASE=http://10.0.2.2:8080

# 실기기/로컬 네트워크
flutter run --dart-define=CORE_API_BASE=http://<your-lan-ip>:8080

E2E

API 레벨 (클라우드/CI에서 실행 가능)

# core-backend :8080 + ai-service :8001 기동 후
export ADMIN_API_TOKEN=dev-admin-token
python3 scripts/e2e_a3.py

A3 체크리스트(가입·연락처·대화·히스토리·draft/L1·에스컬레이션·되돌리기·거부권·화이트리스트)를 HTTP로 검증한다.

에뮬레이터/실기기 UI 탭 (Android SDK 필요)

  1. 초대 코드로 가입 → 말투 샘플 저장(또는 나중에)
  2. 연락처에 상대 사용자 ID 등록 → 대화 시작
  3. 메시지 전송 · 새로고침 후 히스토리 유지
  4. 초안 요청 → L1 패널에서 수정/버리기/승인 발송 → 와카뷰 뱃지 확인
  5. 민감 문장으로 에스컬레이션 → 사후 알림 함 진입
  6. 와카뷰 메시지 되돌리기 · 거부권
  7. 자율성 L0~L2 + 화이트리스트 추가/삭제

로컬 DB (drift + SQLCipher)

말투 샘플·온보딩 플래그는 lib/db/ 암호화 SQLite에 저장한다. 패스프레이즈는 flutter_secure_storage. Linux 개발 호스트에 libsqlcipher.so가 없으면 메모리 폴백으로 기동한다(Android 릴리즈 경로에서는 SQLCipher 사용).

# Linux에서 drift 테스트/암호화 DB를 쓰려면
sudo apt-get install -y libsqlite3-dev libsqlcipher1

푸시 (FCM)

  • 코드: lib/services/push_token_service.dart — Firebase 가능 시 실 토큰, 아니면 install:
  • Master 설정: docs/fcm-setup.md (google-services.json + FCM_SERVER_KEY)

아직 없는 것

  • Master Firebase 시크릿 주입 후 실기기 푸시 스모크 (N4-1/3/4)
  • 오프라인 메시지 큐 / 멀티디바이스 실시간 설정 동기화 고도화
  • 온보딩 말투 UX 디테일 (PoC #1 결과는 맨 마지막에 반영)
  • iOS 빌드 (v1 범위 밖)