Release notes for 1.1.0 were split between an Unreleased section and the version section, so the published notes would have omitted the update-feed and desktop changes. Everything shipping in this version now sits under one `## [1.1.0]` heading. `docs/map/` becomes the entry point for what infrastructure exists per platform and how far each feature is developed, with a documented update protocol so feature work and this map do not drift apart again. The release guide now states that installer binaries live in the update feed rather than the repository.
50 KiB
D3RO Voice 모바일 앱 완성 정본 (SSOT)
상태: ACTIVE 최초 감사 기준: 2026-08-21 /
main@a9c9a1c마지막 release-readiness 스냅샷: 2026-08-29 (Play Console live 재확인, release identity1.1.0/1010001, production AAB 대기) 제품 모바일 런타임:apps/mobile-rn데이터·권한 정본:server/supabase/migrations+ Supabase Auth/Storage/Edge Functions 제품화 재개 핸드오프:MOBILE_PRODUCTIZATION_HANDOFF_2026-08-21.md이 문서는 이전docs/v3/00-mobile-master-plan.md의 미래 로드맵을 대체하는 구현·검증 정본이다.
0. 2026-08-29 출시 게이트 스냅샷
| 게이트 | 현재 증거 | 판정 |
|---|---|---|
| release identity | release/product-version.json: version 1.1.0, Android versionCode / iOS build 1010001 |
source SSOT GREEN; 실제 store artifact 미검증 |
| Play 앱 | app ID 4976102237698469110, package com.d3ro.voice, 상태 임시 |
앱 생성 GREEN, 제출 RED |
| Play 설정 | 0/11, 첫 AAB 0건 | RED |
| App Signing | Play SHA-256 01:00:19:21:DB:4F:33:40:85:CE:21:E4:B8:DE:CC:BD:71:DA:87:67:C5:6E:3B:59:83:2A:A1:C8:29:EA:0D:AB |
Play identity 확인; upload certificate 대조는 첫 AAB 후 |
| upload key | external PKCS12·user-only ACL·Credential Manager·private-key readback GREEN; SHA-256 4F:AC:69:24:...:15:2B:54 |
local key GREEN; CI secret·복구 백업·AAB signer/Console 대조는 RED |
| release evidence key | Ed25519 external private/public pair roundtrip GREEN; public SSOT·keyId 2797d3e6...4a890b7f |
local pair GREEN; CI private-key secret·복구 백업·실제 signed evidence는 RED |
| App Links | source assetlinks.json 3개는 Play SHA-256으로 갱신 |
live는 구 certificate라 배포·public 재검증 전까지 RED |
| Firebase | Console u/0, u/1 모두 D3RO project 없음 |
사용자 승인 후 project·Android app 생성 필요; RED |
| AdMob | App/Banner/Rewarded ID·SSV SSOT 확정 | 검토 필요·광고 게재 제한·store 미연결·결제 프로필 미완료; RED |
| production inputs | production Firebase config·AdMob/upload/evidence CI secret 주입 증거·AAB 없음 | RED |
| closed test | 0/12명, 연속 14일 미시작 | RED |
| production access | disabled | RED |
이 스냅샷의 RED는 내부 구현을 미완성으로 되돌리는 뜻이 아니다. 다만 source/test GREEN을 Play production GREEN으로 확대 해석하지 않는다. Data safety, App content, production access 답변은 실제 Console 문구를 사용자가 검토·승인하기 전에 저장·제출하지 않는다.
0.1 완료 계약
이 작업에서 "완료"는 화면이 존재하거나 타입 검사가 통과했다는 뜻이 아니다. 아래 조건을 모두 만족해야 한다.
apps/mobile-rn의 모든 사용자 노출 버튼·메뉴·딥링크·공유 진입점이 실제 동작한다.- 데스크톱과 Web의 서버 공유 기능은 동일한 Supabase 사용자·구독·데이터에서 읽고 쓴다.
- 모바일에서 불가능한 데스크톱 OS 전용 동작은 모바일 네이티브 동등 기능으로 제공한다.
- 인증·결제·광고 보상·동기화·삭제는 클라이언트 성공 알림만으로 성공 처리하지 않는다.
- Free tier 광고는 실제 광고 SDK 완료 콜백과 서버의 중복 방지 보상 기록을 통과해야 한다.
- 정상·실패·취소·재시도·오프라인·중복 요청·권한 거부·세션 만료 경로를 자동화한다.
- Android 에뮬레이터에서 설치된 APK를 대상으로 전체 E2E를 수행하고 증거를 남긴다.
- 실행 코드에 미구현 placeholder, 가짜 성공 타이머, 개발 우회 로그인, 무반응 Pressable을 남기지 않는다.
- 각 작업은 코드, 자동 테스트, 에뮬레이터 증거를 모두 확보한 뒤에만
[x]로 바꾼다.
1. 정본 경계와 보존 규칙
apps/mobile-rn: Android/iOS 제품 모바일 앱. 모든 신규 구현은 여기에 한다.apps/mobile: Expo 51 기반 과거 스켈레톤. 2026-09-13 제거 완료 — 이중 구현 금지, 이력은 git에 보존.apps/web: 서버 공유 기능과 사용자 데이터 UX의 비교 기준.apps/desktop: 데스크톱 기능 목록과 로컬 전용 기능의 의미 기준.packages/api-client: Supabase 타입과 공용 API 호출의 정본. 모바일에서 임의 테이블 타입을 중복 작성하지 않는다.packages/core: 기능·구독·광고·오류 도메인 타입의 정본.packages/ui-native: 모바일 디자인 토큰과 공용 컴포넌트 정본.- 기존 dirty worktree와
main의 미푸시 커밋 2개를 보존한다. 관련 없는 바이너리·Web·스크립트 변경을 되돌리거나 함께 정리하지 않는다. - 비밀값은 저장소에 하드코딩하지 않는다. 빌드 시 주입하고, 누락 시 기능을 숨겨 성공처럼 보이게 하지 말고 진단 가능한 오류로 닫는다.
2. 2026-08-21 초기 감사 결과
아래 표는 구현 전 기준선이다. 현재 판정은 바로 다음
2.1과 4절 체크리스트, 7절 실행 증거를 따른다. 기준선의 실패 문구를 현재 상태로 읽으면 안 된다.
| 영역 | 현재 사실 | 판정 |
|---|---|---|
| 앱 기반 | RN CLI 0.85 / React 19, Android 네이티브 프로젝트와 서명 APK가 존재 | 기반만 존재 |
| 화면 | Login, Dash, History, Record, Talk, Settings, ProPaywall 7개 화면 | 기능 동등성 미달 |
| Supabase | SUPABASE_URL과 anon key가 빈 문자열이며 dummy fallback으로 크래시만 회피 |
실제 인증·데이터 불가 |
| 세션 라우팅 | 앱은 항상 Login을 첫 화면으로 열며 인증 상태에 따른 root 전환이 없음 | 실패 |
| 회원가입 | 회원가입 문구는 Pressable이지만 handler와 화면이 없음 | 실패 |
| OAuth | 브라우저 호출 코드는 있으나 설정 주입·콜백 수명주기·취소/오류 검증이 불완전 | 미검증 |
| 계정 관리 | 이메일 표시와 로그아웃 확인만 존재. 프로필 수정·비밀번호·연결 계정·삭제 없음 | 실패 |
| 녹음 | recorder hook이 placeholder이며 stop 결과가 항상 null |
실패 |
| 파일 전사 | document picker, content URI 처리, 업로드 진행/취소 화면 없음 | 없음 |
| 히스토리 | 최대 50개 조회만 수행. 필터는 데이터에 적용되지 않고 상세/편집/삭제/공유 없음 | 실패 |
| AI 대화 | 사용자 말풍선만 로컬 state에 추가하고 서버 LLM 응답을 호출하지 않음 | 실패 |
| 설정 | 언어·자동 교정·햅틱·STT 스위치가 고정값이며 저장되지 않음 | 실패 |
| 결제 | 1.8초 대기 후 "결제 완료" 알림을 띄움 | 가짜 성공, 출시 차단 |
| 구매 복원 | 1.2초 대기 후 성공 알림을 띄움 | 가짜 성공, 출시 차단 |
| 광고 보상 | 2.5초 대기 후 로컬 토큰을 50 증가시킴 | 가짜 보상, 출시 차단 |
| 광고 인프라 | 데스크톱 mediation 타입·adapter·테스트가 있으나 다수 adapter가 합성 bid/creative를 반환. 모바일 광고 SDK 없음 | 기반 참고만 가능 |
| 백엔드 | Auth/RLS/Storage/STT/LLM/팀/Push/Stripe/Payple/Admin 함수와 스키마가 존재 | 재사용 가능, 모바일 IAP·광고 원장 없음 |
| 신원 체계 | Supabase Auth/Postgres, 별도 .NET JWT/SQLite, 데스크톱 로컬 license가 서로 다른 사용자·권한을 가짐 | 단일 SSOT 필요 |
| STT 실패 | Supabase와 .NET STT가 provider 전체 실패 때 합성 transcript를 성공으로 반환 가능 | 가짜 성공, 출시 차단 |
| 배포 APK | 공개 APK가 application-debuggable이며 arm64 단일 ABI. 보유 AVD는 x86_64 |
에뮬레이터 설치 불가 |
| 테스트 | 모바일 Jest smoke 1개 외에 기능 단위·통합·기기 E2E가 없음 | 실패 |
| Android 권한 | 제품 manifest에는 INTERNET 외 녹음·알림·미디어/foreground service 권한이 없음 | 실패 |
2.1 현재 실행 스냅샷
| 묶음 | 현재 판정 | 확인된 증거 / 남은 게이트 |
|---|---|---|
| Auth·계정 | 구현·자동화 GREEN, 외부 OAuth·privacy purge 기기 E2E 대기 | auth/signup/invite 경계는 최신 exact APK .11에서 PASS. Keychain 세션, 중앙 purgeAllAccountLocalData, cold no-session·SIGNED_OUT·refresh session loss·A→B 전환·실패 재시도 경계는 전체 모바일 57 suites/353 tests에 포함돼 GREEN. 실제 token-expiry 강제 로그아웃·logout/delete/provider 연결/해제 기기 E2E와 Google/GitHub/Apple 동의→callback은 남음 |
| 온보딩·테마 | 구현·기기 journey GREEN | 신규/기존 분기, skip/replay, 계정별 preference merge, system/light/dark, reduced motion, 알림·마이크 권한 상태 구현. production preference 0→skip→1, Android PID 유지, 5.8초 내 Main, navigation warning 0을 실측 |
| 녹음·전사·Talk | 핵심 경로 GREEN | API 34 microphone FGS, 지속 알림, pause/resume/discard, 실제 통화 audio-focus, 프로세스 kill 후 WAV 복구, 파일 import, cloud STT fail-closed, on-device Whisper, Claude SSE, Android TTS를 통합 APK에서 확인. STT provider 호출 전 원자 quota reservation·실패 환불은 20-way 동시성으로 검증. Android ACTION_SEND 수신은 허용 MIME·크기·provider 예외·MP4 AAC 추출을 fail-closed로 구현했고 API 34 instrumentation 4/4(CSPRNG 1 + share 3)와 별도 UID 외부 ContentProvider APK→ACTION_SEND→Record→durable queue→cancel cleanup E2E가 GREEN |
| 데이터 portability | 구현·공유 E2E GREEN | 00021 atomic export/restore, 손상/타 사용자/충돌 rollback, legacy import를 local integration으로 확인. portable_exports→FileProvider shared_exports 경계와 PDF Print/DOCX chooser·30초 cleanup을 실제 기기에서 확인 |
| History·회의 | 실제 데이터·회의 생성 계약 GREEN | Supabase history pagination/search/favorite/CAS, Web↔mobile history E2E, meetings/memos/documents RLS/CAS, meeting recording lifecycle 구현. 00025의 제목·참석자·4개 언어·소유 템플릿 원자 생성은 2계정 43 assertions와 competing-payload PT409로 검증. speaker/audio timestamp와 최종 교차 앱 E2E는 남음 |
| Teams·Push | 팀 GREEN, 외부 Push 대기 | production 17 assertions와 local 36 assertions로 원자 팀/초대/RLS/role/device token 계약 확인. durable push outbox 00015~00020과 logout device 1→0 확인. 실제 FCM 수신은 Firebase/FCM 자격 증명·cron 배포가 필요 |
| Billing·Ads | test 광고와 production AdMob identity/SSV 준비, store·실제 지급 E2E RED | Google Play restore는 실제 store list→모든 token 서버 검증→entitlement snapshot 일치 후에만 성공. Google 공식 test adaptive banner와 rewarded AdActivity 완주를 실측했다. production app ca-app-pub-1039714767792854~6427959892, banner /9840591290, rewarded /2255790918, 50 cloud_ai_tokens, SSV URL, Edge v13, durable receipt 원장은 SSOT에 반영했다. 그러나 live는 검토 필요, 광고 게재 제한, store 미연결, 결제 프로필 미완료다 |
| Admin | 서버·Web·모바일 E2E와 production DB·Edge 배포 GREEN | .NET 21/21, 00023 관리 integration 25 assertions, Edge/JWT 47 assertions와 TLS Chromium E2E GREEN. 모바일 API 34에서 ordinary/manager/admin/super_admin 및 stale 강등을 55 assertions로 실측: Free test 광고, Pro 광고 미요청, 관리자 메뉴/API 차단, 구독 수정, 역할 경계·변경, 삭제 확인·취소, stale JWT 403와 민감 state purge가 모두 PASS. fixture 잔존 0. production 00023 및 admin Edge 4개 배포 후 익명 GET은 모두 401 authentication_required + Cache-Control: no-store로 재검증 |
| 품질·배포 | exact-APK 에뮬레이터 gate GREEN, production 배포 RED | mobile ESLint 0, typecheck GREEN, 전체 Jest 57 suites/353 tests GREEN은 2026-08-24 실행 증거다. universal non-debuggable TEST-DEMO 0.0.0-e2e.20260821.11/202608221을 API 34에 fresh install해 cold launch·auth/signup/invite를 검증했지만 production artifact가 아니다. 2026-08-29 release identity 1.1.0/1010001, local upload key, Ed25519 evidence keypair, AdMob identity는 확정했지만 production Firebase·CI secret 주입·AAB·Play track·Fold6 Play 설치 증거는 없다 |
3. 플랫폼 동등성 원칙
| 데스크톱 기능 | 모바일 동등 기능 |
|---|---|
| 전역 단축키 녹음 | 앱 바로가기, 알림 action, 홈 화면 quick action, 앱 내 큰 녹음 CTA |
| OS 현재 앱에 텍스트 삽입 | 복사, Android 공유 시트, 선택한 앱으로 공유 |
| 로컬 Whisper/Ollama | 모바일 기기 지원 여부를 감지하고, 기본은 인증된 Cloud STT/LLM. 결과·쿼터·오류 계약은 동일 |
| 파일 드롭 | Android Storage Access Framework 문서 선택과 다른 앱의 ACTION_SEND/ACTION_VIEW 수신 |
| 데스크톱 SQLite | Supabase SSOT + 암호화된 모바일 캐시·업로드 큐 |
| 시스템 오디오 회의 녹음 | 마이크 foreground service 녹음. Android 정책상 캡처 가능한 미디어 projection은 별도 명시 동의 후만 사용 |
| 데스크톱 설정 모달 | 모바일 설정 navigation stack과 계정·기기·데이터 관리 화면 |
4. 전체 기능 매트릭스와 작업 등록
상태 표기: [ ] 미완료, [~] 구현 중, [x] 코드+자동화+에뮬레이터 증거 완료, [!] 외부 콘솔/계정 증거 대기.
G — 거버넌스·기반
- G-001 제품 모바일 런타임을
apps/mobile-rn으로 확정하고 본 문서에 기록 - G-002
apps/mobile참조 코드에서 재사용할 기능을 선별하고 이중 런타임 의존 제거 — 2026-09-13apps/mobile삭제,sync-version.mjs/package-lock.json정리,version:checkGREEN - G-003 모바일 환경 설정 스키마 작성: Supabase URL/anon key, API origin, OAuth redirect, AdMob app/unit IDs, Play product IDs
- G-004 debug/test/prod 설정 분리와 시작 시 구성 진단 화면 구현
- G-005 하드코딩된 release signing 자격 증명을 로컬/CI secret 주입으로 이동
- G-006 공용 API·DB 타입을
packages/api-client에서 소비하고 화면별 임시 타입 제거 - G-007 오류 코드·사용자 메시지·관찰 가능 로그를 공용 규약으로 통일
- G-008 legacy bundle/APK 생성물을 소스 변경과 분리하고 재현 가능한 build script 확정
- G-009 Supabase Auth/profile/subscription을 단일 사용자·entitlement SSOT로 확정하고 .NET 계정은 제거 또는 명시적 매핑
- G-010 Android application ID, iOS bundle ID, OAuth client, 딥링크 scheme을 하나의 제품 식별자로 통일
- G-011 노출된 signing/Forgejo/OAuth/JWT 자격 증명을 폐기·회전하고 CI secret으로 이동
- G-012 .NET 고정 관리자 seed·정적 salt SHA-256 비밀번호·fallback JWT secret 제거
A — 인증·회원가입·본인 계정 관리
- A-001 auth bootstrap splash와 session restore 구현
- A-002 인증 상태에 따라 Login/Main/Onboarding을 원자적으로 전환
- A-003 이메일 로그인 입력 검증·rate limit 메시지·세션 저장
- A-004 이메일 회원가입 화면과 약관 동의, 중복 계정 오류, 이메일 확인 대기 화면
- A-005 이메일 확인 딥링크와 확인 후 session 전환
- A-006 비밀번호 찾기 메일 요청·recovery 딥링크·새 비밀번호 설정
- A-007 Google OAuth PKCE 시작/취소/콜백/코드 교환/재실행 검증
- A-008 GitHub OAuth PKCE 시작/취소/콜백/코드 교환 검증
- A-009 Apple 로그인은 iOS에서 네이티브 정책 준수, Android에서는 지원 여부를 명확히 표시
- A-010 OAuth identity 충돌·동일 이메일 연결·provider 오류 처리
- A-011 프로필 이름·아바타·locale 조회/편집과 optimistic rollback
- A-012 본인 이메일·provider·가입일·마지막 로그인·구독 상태 확인 화면
- A-013 비밀번호 변경과 재인증 요구 처리
- [~] A-014 연결된 로그인 provider 목록과 연결/해제 안전장치 — 코드·Jest GREEN, 실제 provider 동의/연결/해제 E2E 대기
- [~] A-015 모든 로컬 민감 캐시를 지우는 로그아웃 및 navigation reset — Keychain·recorder·durable queue purge 코드·Jest GREEN, 최신 APK 재검증 대기
- [~] A-016 계정 삭제: 재인증, 명시 확인, 서버 cascade/보존 정책, 완료 후 로컬 purge — 서버 성공 후 로컬 purge 코드·Jest GREEN, 최신 APK 재검증 대기
- [~] A-017 access token 만료·refresh 실패·강제 로그아웃 E2E — 중앙 privacy purge와 session-loss/race/failure-retry Jest GREEN, 실제 token-expiry 기기 E2E 대기
- A-018 release 빌드에서 dev bypass와 dummy auth 성공 경로 완전 제거
O — 온보딩·튜토리얼·테마·접근성
- O-001 첫 실행 welcome과 기존 사용자/신규 사용자 분기
- O-002 로그인 전 개인정보·클라우드 처리·녹음 권한 설명
- O-003 마이크 권한 요청/거부/다시 묻지 않음/설정 이동
- O-004 알림 권한은 가치 설명 뒤 요청하고 거부 시 기능 저하 안내
- O-005 첫 녹음→전사→공유를 안내하는 단계별 튜토리얼
- O-006 주요 탭과 파일 가져오기·동기화·결제 관리 튜토리얼
- O-007 튜토리얼 다시 보기·건너뛰기·완료 상태 동기화
- O-008 system/light/dark 테마와 D3RO 토큰 기반 렌더링
- O-009 테마·언어·햅틱·자동 교정·STT 옵션 저장 및 기기간 동기화
- O-010 글자 확대, TalkBack label/role, focus order, 48dp 터치 영역, 색 대비 검증
- O-011 reduced motion과 애니메이션 비활성 경로
- O-012 한국어/영어 필수 전체 번역과 하드코딩 문자열 제거
D — 데이터 가져오기·동기화·오프라인
- D-001
user_settings,devices,audio_files,processing_jobs스키마·RLS·Realtime 확정 - D-002 모바일 기기 등록, last seen, push token, 앱 버전 갱신
- D-003 연결 기기 목록·현재 기기 표시·원격 연결 해제
- D-004 데스크톱/Web에서 생성한 history/meeting/document/dictionary/knowledge/team 데이터 조회
- D-005 모바일 변경을 데스크톱/Web에 Realtime 또는 재조회로 반영
- D-006 최근 데이터 암호화 캐시와 로그인 사용자별 격리
- D-007 오프라인 생성·편집 queue, 재시도 backoff, 앱 재시작 복구
- D-008 충돌 정책: 서버 revision/updated_at 기반 감지와 사용자 선택 또는 안전 병합
- D-009 pull-to-refresh, background refresh, stale/offline 표시
- D-010 기존 데스크톱 내보내기 파일 가져오기와 형식 검증
- D-011 Web/모바일 JSON·CSV·TXT 호환 가져오기와 중복 idempotency
- D-012 데이터 전체 내보내기, 계정 데이터 다운로드, 공유
- D-013 부분 실패·중복 import·다른 사용자 데이터·손상 파일 fail-closed 테스트
- D-014 앱 삭제/재설치·다른 기기 로그인 후 클라우드 복원 E2E
R — 녹음·모바일 파일·전사·공유
- R-001 Android
RECORD_AUDIOruntime permission과 manifest 선언 - R-002 실제 RN recorder 모듈로 시작/일시정지/재개/중지/취소 구현
- R-003 오디오 레벨 meter와 timer가 실제 recorder state에서 파생
- R-004 앱 background 전환·전화/오디오 focus loss·프로세스 종료 복구
- R-005 Android foreground service와 지속 알림으로 장시간 녹음
- R-006 저장 공간 부족·마이크 사용 중·권한 철회·장치 오류 처리
- R-007 녹음 파일 메타데이터, content type, duration, checksum 생성
- R-008 Supabase Storage 사용자 경로 업로드와 RLS 검증
- R-009 업로드 진행률·취소·재시도·resume 가능한 queue
- R-010 STT 함수 호출, 인증/쿼터/413/415/429/5xx 오류 계약 처리 — provider 호출 전 원자 reservation, 20-way 동시성·overage·환불·ACL integration GREEN
- R-011 전사 job 상태 Realtime/poll fallback과 앱 재시작 복원
- R-012 완료 transcript/history/audio_files를 한 transaction 계약으로 연결
- R-013 Android 파일 선택기로 m4a/mp3/wav/aac/flac/ogg/mp4/mov/webm 선택
- R-014
content://, cloud provider, 한글/공백 파일명, MIME 불일치 안전 처리 - R-015 대용량 파일 크기·시간 제한, 청크 업로드, 진행률, 취소, 재개
- R-016 다른 앱 공유 시트
ACTION_SEND/ACTION_VIEW오디오·비디오 수신 — native instrumentation 3/3와 별도 UID Android ContentProvider APK의 실제ACTION_SEND→Record→durable queue→cancel cleanup E2E GREEN - R-017 transcript/요약/회의록을 텍스트·Markdown·파일로 공유
- R-018 원본 오디오 공유는 사용자가 명시 선택한 경우에만 임시 URI 권한으로 제공
- R-019 전사 결과 복사·편집·저장·재처리·삭제
- R-020 녹음/파일 전사 정상·실패·취소·오프라인·재시작 E2E
- R-021 Supabase/.NET STT provider 전체 실패 시 합성 transcript 성공을 제거하고 fail-closed — 502/503만 반환, 합성 성공 경로 0, Deno/.NET 계약 테스트 GREEN
- R-022 .NET STT endpoint 인증·사용자 quota를 강제하고 익명 user fallback 제거 — 사용자 경로는 Supabase JWT+원자 quota SSOT, .NET provider endpoint는 32-byte service token 전용. anonymous 401, direct authenticated legacy 410, exact internal token만 provider orchestration
H — 히스토리·회의·문서
- H-001 History 사용자 범위 pagination과 날짜 그룹
- H-002 전체/즐겨찾기/처리중 filter를 실제 query/state에 적용
- H-003 검색, 날짜/모드/상태 정렬, empty/error/retry UI
- H-004 히스토리 상세: 원문·교정문·메타데이터·오디오 재생
- H-005 즐겨찾기, 제목 변경, 편집, 재처리, 삭제, 복구 가능 확인
- H-006 회의 생성: 제목·참석자·언어·템플릿
- H-007 회의 중 녹음·메모·부분 전사 timeline
- H-008 회의 종료와 전체 transcript 병합·처리 상태
- H-009 요약·결정사항·액션 아이템·회의록 생성
- H-010 transcript/summary/documents 탭 조회·편집·동시 수정 충돌
- H-011 오디오 seek와 transcript timestamp 연동
- H-012 PDF/DOCX/TXT/Markdown 내보내기와 Android 공유
- H-013 회의 목록 search/filter/sort/delete/share
- H-014 화자 구분 상태·화자명 편집·미지원 fallback
- H-015 Web↔모바일 동일 회의 교차 편집 E2E
F — 데스크톱/Web 전체 기능의 모바일 화면
- F-001 Dashboard 통계·사용량·처리 job·구독·동기화 상태를 실제 데이터로 표시
- F-002 Dictionary 목록/검색/추가/편집/삭제/import/export/sync — CRUD/sync GREEN, export는
data-portabilityCSV/TXT, import는 CSV/JSON/TXT - F-003 Custom instructions 목록/활성화/CRUD/reorder/sync
- F-004 Voice commands 목록/활성화/CRUD와 모바일 실행 가능한 action 구분
- F-005 Actions 실행, 권한 확인, 실행 결과·실패 기록
- F-006 AI text chat server 호출, streaming, 취소, retry, session history
- F-007 Push-to-talk→STT→LLM→TTS 음성 대화와 재생/중단
- F-008 custom instruction과 대화 backend/model/voice 선택
- F-009 Knowledge 문서 목록/검색/추가/삭제와 RAG query
- F-010 모바일 파일에서 지식 문서 가져오기와 처리 상태
- F-011 Templates 목록/선택/CRUD와 회의·전사 문서 생성 연동
- F-012 Memos 목록/CRUD/search/share/sync
- F-013 연결 상태·백엔드 건강·quota를 실제 probe 결과로 표시
- F-014 데스크톱 전용 기능은 이유와 모바일 대안을 명시하고 무반응 UI를 두지 않음
T — 팀·관리·알림
- T-001 팀 목록/생성/이름 변경/삭제와 role 권한
- T-002 이메일/링크 초대, 딥링크 수락, 만료·중복·다른 계정 처리
- T-003 팀원 목록, admin/member/viewer 권한, 제거·나가기
- T-004 팀 회의·문서 공유와 RLS 교차 사용자 음성/문서 접근 차단
- T-005 팀 코멘트·활동 feed —
team_activities+create_team_activityRPC + Realtime, TeamDetail 활동 카드 (알림 연동은 T-010/011 범위) - T-006 일반 사용자의 본인 데이터 관리와 관리자 전용 기능을 분리 — ordinary UI에서 Admin 숨김·관리 API request 0, manager/admin/super 분기 API 34 E2E PASS
- T-007 admin/manager role 사용자는 사용자·구독·결제 감사 정보를 모바일에서도 안전 조회 — manager read/subscription update, stale JWT 403와 target/modal purge API 34 E2E PASS
- T-008 role 변경·구독 수정 등 파괴적 관리 동작은 재확인·감사 로그·서버 권한 검증 — admin role 범위·delete confirm/cancel, super manager→admin, RPC readback과 cleanup 0 E2E PASS
- T-009 push token 등록/교체/로그아웃 삭제와 중복 방지
- T-010 전사 완료·팀 초대·댓글·결제 상태 push 수신과 해당 화면 딥링크
- T-011 알림 카테고리 설정·OS 권한 미허용 fallback
- T-012 foreground/background/terminated 상태 알림 E2E
- T-013 Admin API 장애 때 realistic mock 운영 데이터를 반환하지 않고 명시 오류·stale 상태 표시 — stale-role 403 실측에서
admin-error노출 및 기존 민감 state 제거
M — 구독·구매·결제·Free tier 광고
- M-001 서버 구독 상태와 quota를 읽는 entitlement provider 구현
- M-002 Web Payple/Stripe 구독을 모바일에서 자동 인식하고 중복 구매 경고
- M-003 Android Google Play Billing 라이브러리와 product ID 구성
- M-004 Play product/offer 조회와 스토어가 반환한 현지 가격·기간 표시
- M-005 Pro/Pro+ 구매 시작, 사용자 취소, pending, already-owned, 오류 처리
- M-006 purchase acknowledgement와 앱 재시작 시 미완료 purchase 복구
- M-007 구매 token을 클라이언트에서 신뢰하지 않는 서버 검증 함수
- M-008 검증 결과를 idempotent purchase 원장과 subscriptions entitlement에 반영
- M-009 Real-time Developer Notifications 또는 정기 검증으로 갱신·취소·환불·보류 반영
- M-010 구매 복원은 실제 스토어 조회+서버 검증 후에만 성공 표시
- M-011 구독 관리 버튼을 Google Play 구독 관리 화면으로 연결
- M-012 현재 플랜·만료/갱신일·결제 provider·사용량·결제 내역 표시
- [~] M-013 가격·기능표를 서버/스토어 SSOT로 통일하고 hardcoded 가짜 가격 제거 — Web billing catalog·desktop checkout server readback·모바일 Play product 가격 사용, production Play/Payple/Stripe 교차 검증 대기
- M-014 Google Mobile Ads SDK와 test/prod app ID·unit ID 분리
- M-015 Free entitlement에만 adaptive banner를 안정적인 앱 레이아웃 영역에 표시
- M-016 Pro/Pro+ entitlement에서는 광고 request 자체를 하지 않음
- M-017 rewarded ad load/show/earned/closed/failure state machine
- M-018 광고를 끝까지 보지 않거나 SDK 오류 시 보상 금지
- M-019 서버 side verification 또는 signed reward nonce와 광고 보상 원장
- M-020 동일 광고·nonce·사용자 중복 보상 차단과 cooldown/rate limit
- M-021 서버 확정 잔액을 재조회한 뒤 UI에 반영하고 로컬 임의 증가 제거
- M-022 광고 동의/연령/지역별 privacy options와 consent 상태 저장
- M-023 광고 차단·네트워크 없음·no fill에서 핵심 Free 기능은 안전 fallback
- M-024 debug 에뮬레이터에서 Google test banner/rewarded ad E2E
- M-025 Play Billing license tester에서 구매·복원·취소/pending E2E
- M-026 결제/광고 receipt·token·개인정보를 로그와 analytics에 노출하지 않음
- M-027 Payple webhook 요청 인증·서명 검증과 replay 방지
- M-028 Stripe
pro_plus상품 계약과 DB tier를 통일하고 subscriptions/profiles drift 방지 - M-029 데스크톱 임의 checkout URL·무조건 성공 payment verify·legacy license 우회 제거 — 인증된 Stripe/Payple Edge-only 계약, trusted URL·server readback·deadline·idempotency fail-closed와 전체 desktop 590 tests GREEN
Q — 자동화·Android 에뮬레이터·출시 게이트
- Q-001 모바일 typecheck, lint, Jest 기본 gate 정비
- Q-002 auth/account service 단위·통합 테스트
- Q-003 recorder/upload/job/file import service 단위·통합 테스트
- Q-004 sync/cache/conflict/retry 테스트
- Q-005 subscription/IAP verification/idempotency 테스트
- Q-006 ad entitlement/reward/cooldown/fraud 테스트
- Q-007 Supabase migration을 새 로컬 DB에 전부 적용
- Q-008 RLS cross-user/anonymous/admin 권한 SQL 테스트
- Q-009 Edge Function auth/quota/content type/size/idempotency 테스트
- [~] Q-010 Android debug·release APK clean build — universal debug와 non-debuggable E2E 양 ABI clean build GREEN, production signed release APK/AAB는 외부 secret gate
- [~] Q-011 JS bundle이 포함된 release APK의 offline cold start — embedded bundle non-debuggable E2E APK cold start GREEN, production signed release artifact는 대기
- Q-012 에뮬레이터 API 35+ 생성·부팅·초기화 script
- Q-013 fresh install→onboarding→signup/login→logout E2E
- Q-014 OAuth provider redirect→callback→session→Main E2E
- Q-015 녹음 권한→실제 오디오 fixture 주입/녹음→전사 결과 E2E
- Q-016 파일 picker→fixture 선택→upload→전사→상세→공유 E2E
- Q-017 Web seeded 데이터→모바일 조회/편집→Web 확인 sync E2E
- Q-018 Free banner/rewarded test ad와 Pro 광고 미요청 E2E — official Google test ad 실측, ordinary Free 광고 노출과 manager/admin Pro 광고 비노출·미요청 API 34 PASS
- Q-019 Play Billing test purchase/restore/manage E2E
- Q-020 모든 탭·설정·팀·관리·실패 복구 journey E2E
- Q-021 회전·폰트 확대·TalkBack·dark/light·작은/큰 화면 visual gate
- Q-022 airplane mode·process kill·token expiry·server 5xx·중복 tap 회복 E2E
- [~] Q-023 앱 로그 crash/ANR/React error/민감정보 0건 확인 — exact
.9auth/signup/invite/small-screen 및 admin role journeys에서 fatal/ANR/React fatal 0, production provider journey 민감정보 로그 감사 대기 - Q-024 APK package/version/signature/SHA-256와 설치된 앱 버전 증거
- Q-025 최종 증거 표에 명령·결과·artifact·스크린샷/영상 경로 기록
- Q-026 Node 24 LTS/JDK 17/Gradle 환경을 로컬·CI에서 통일
- [~] Q-027 debug x86_64+arm64, release arm64 APK/AAB ABI 정책과 에뮬레이터 호환성 검증 — universal E2E APK 정책 GREEN, 실제 production arm64 APK/AAB CI 검증 대기
- [~] Q-028 공식 배포가
assembleRelease비-debuggable artifact만 허용하도록 fail-closed — signed evidence·hash/version/package/cert/prod AdMob·create-only 경계와 negative self-test GREEN, 실제 production AAB/CI/secrets 대기
5. 구현 순서와 게이트
- Gate 0 — G 기반, 실제 Supabase 구성, auth root, 테스트 harness
- Gate 1 — A 계정 전체 + O 온보딩/권한/테마
- Gate 2 — R 녹음·파일 전사 + H 히스토리 상세·공유
- Gate 3 — D 동기화/가져오기/오프라인 + F 전체 기능 화면
- Gate 4 — H 회의/문서 + T 팀/관리/알림
- Gate 5 — M 실제 Play Billing·광고·서버 검증
- Gate 6 — Q 전체 자동화와 Android 에뮬레이터 clean-room E2E
각 Gate는 다음 Gate로 가기 전 typecheck/unit/integration와 해당 에뮬레이터 journey를 통과한다. 뒤 단계에서 회귀가 발견되면 해당 작업을 다시 [ ]로 되돌리고 수정·재검증한다.
6. 외부 시스템 준비 항목
아래 항목은 구현을 멈추는 이유가 아니다. Google test ID, 로컬 Supabase, fixture account로 코드와 자동화를 먼저 완성한다. 다만 production 완료 표시는 실제 콘솔 증거가 있어야 한다.
- [~] EXT-001 Supabase production URL/anon key, redirect allow-list, OAuth provider secrets — production Auth와 Google provider entry는 GREEN, GitHub/Apple provider secret 및 실제 mobile consent callback은 남음
- [!] EXT-002 Play app-signing SHA-256은 확인했지만 Android OAuth/Firebase client의 package·SHA-1/SHA-256 등록과 live App Links 배포가 남음
- [!] EXT-003 Google Play Console 앱
4976102237698469110/ packagecom.d3ro.voice는 생성. Pro/Pro+ base plan/offer/product IDs와 track 설정은 남음 - [!] EXT-004 Play Billing license tester와 테스트 결제 수단
- [!] EXT-005 Google service account, Android Publisher API, RTDN Pub/Sub
- [~] EXT-006 AdMob app
ca-app-pub-1039714767792854~6427959892, banner/9840591290, rewarded/2255790918, SSV 설정 — identity/URL SSOT는 확정.검토 필요·광고 게재 제한·결제 프로필·store 미연결·test-device 실제 지급 E2E 대기 - EXT-007 개인정보 처리방침·이용약관·계정 삭제 공개 URL — NAS host/runtime에 동일 해시로 좁게 배포,
/privacy/,/terms/,/delete-account/외부 HTTPS 200·정확한 title·삭제 요청 링크 확인. 모바일 Settings와 Paywall에서 canonical URL 진입 - [!] EXT-008 local upload key·Ed25519 evidence keypair는 ACL/readback/roundtrip GREEN. production Firebase/AdMob/signing/evidence secret의 CI 보관·보호 환경 승인·복구 백업 및
1.1.0/1010001production AAB workflow는 대기 - [!] EXT-011 Firebase Console
u/0,u/1모두 D3RO project 0개 — 사용자 action-time 승인 후 production project·Android app·Play fingerprint·FCM 생성/연결 - [!] EXT-009 Fold6 physical-device install/share/OAuth/purchase 증거 — exact
.11APK Taildrop 전송 완료, 사용자 설치·실행·공유/OAuth/구매 확인 필요 - [!] EXT-010 Play closed test 12명·연속 14일 완료와 production access 승인 — 2026-08-29 현재 0명, access disabled
7. 검증 증거 표
| Gate | 명령/시나리오 | 결과 | 증거 경로 | 확인 시각 |
|---|---|---|---|---|
| Historical baseline | git status --short --branch |
2026-08-21 당시 main이 remote보다 2 commit 앞서고 dirty 변경이 다수였다. 현재 release SHA로 재사용하지 않는 역사 증거다 |
본 문서 1절 | 2026-08-21 |
| Mobile lint | npm --prefix apps/mobile-rn run lint |
GREEN, warning/error 0 (--max-warnings=0) |
apps/mobile-rn/.eslintrc.js, package.json |
2026-08-21 |
| Mobile typecheck | npm --prefix apps/mobile-rn run typecheck |
GREEN | apps/mobile-rn/tsconfig.json |
2026-08-21 |
| Mobile unit | npm --prefix apps/mobile-rn test |
전체 통합 tree 57 suites / 353 tests GREEN; 중앙 account-local privacy purge, cold/session-loss/A→B auth 경계, secure logout, identity safety, mobile admin, rewarded/banner retry·template/memo·meeting creation·recording language·generation idempotency 포함 | apps/mobile-rn/__tests__ |
2026-08-24 |
| Supabase local | migration-up + shadow replay 00001~00028 및 domain integration | 기존 domain integration에 더해 AdMob receipt 원장의 unknown/ineligible/cooldown replay, account-delete unlink, ACL, 교차 사용자·동시 요청을 검증했다. mobile-platform 85/85, reward race 2회 연속, SSV Deno 6/6, db lint error 0, shadow diff empty, fixture cleanup 0 | server/supabase/migrations/20260821000028_ad_reward_receipt_replay_protection.sql, server/supabase/tests, server/supabase/functions/_shared/admob-ssv.test.ts |
2026-08-24 |
| Android build | :app:assembleDebug -PreactNativeArchitectures=arm64-v8a,x86_64 |
universal BUILD SUCCESSFUL; 두 ABI의 screens/gesture/Nitro/Whisper SO 완전성 확인 후 x86_64 clean cold launch GREEN, SHA-256 E4647A4C041174DF2B2F094EF7BB61B4B01DD10A379DB32CCBE4105231E04A7C |
apps/mobile-rn/android/app/build/outputs/apk/debug/app-debug.apk, scratch/demo/d3ro-mobile-dual-abi-installed.png |
2026-08-21 |
| Latest Android E2E test artifact | JDK 17 :app:assembleE2e -PreactNativeArchitectures=arm64-v8a,x86_64 + artifact/build-config verifiers |
BUILD/verifier GREEN; com.d3ro.voice, version 0.0.0-e2e.20260821.11/202608221, non-debuggable, embedded bundle 3,808,068 B·Whisper model 77,691,713 B/SHA 검증, Google test AdMob ID, arm64+x86_64. APK 146,739,935 B, SHA-256 74035B69DB0A564846DF5ED4B85CA5D0E2289D5BB7D73DEE02C35DFD57380C2B. API 34 exact-APK fresh install와 cold launch GREEN. production artifact가 아니다 |
apps/mobile-rn/android/app/build/outputs/apk/e2e/app-e2e.apk, scripts/ci/verify-android-artifact.mjs, scripts/ci/verify-mobile-build-config.mjs |
2026-08-21 |
| Public Forgejo distribution | 최신 E2E TEST-DEMO 고유 asset upload + anonymous redownload hash 대조 | PENDING; .11 SHA-256 74035B69…380C2B 공개 업로드·anonymous redownload 검증은 수행하지 않음 |
Forgejo release asset | 2026-08-21 |
| Mobile release boundary | npm run release:mobile:boundary:test + source-contract/security/syntax/YAML checks |
GREEN; release mode·expected version/package/cert/prod AdMob·Ed25519 signed evidence와 artifact hash 일치, immutable snapshot, hardlink/reparse/path-swap/static APK 우회·overwrite·test AdMob/debug signer/nonrelease 거부를 검증. 실제 production APK/AAB에는 아직 실행하지 않음 | scripts/ci/mobile-release-evidence-lib.mjs, scripts/ci/verify-mobile-release-boundary.mjs, .github/workflows/release.yml |
2026-08-21 |
| Production Android release gate | release/config/artifact/provenance self-tests + Play/Firebase/AdMob live 재확인 | release identity 1.1.0/1010001, Play app ID 4976102237698469110, package com.d3ro.voice, app-signing SHA-256, local upload/evidence key, AdMob identity를 확인했다. Play는 임시, 설정 0/11, AAB 0건, closed tester 0/12명, production access disabled다. Firebase project·CI secret 주입·AAB가 없으므로 현재 판정은 RED다 |
release/product-version.json, release/android-release-identity.json, scripts/ci/verify-mobile-release-config.mjs, scripts/ci/verify-android-artifact.mjs, live consoles |
2026-08-29 |
| App Links release identity | source/live exact certificate 대조 | site/public, apps/web/public, apps/api-server/wwwroot의 source 3개는 Play app-signing SHA-256으로 갱신. live는 아직 폐기된 과거 certificate를 반환하므로 deploy·public 재검증 전까지 RED |
*/.well-known/assetlinks.json, scripts/ci/verify-android-app-links.mjs, live d3ro.chanpaca.net |
2026-08-29 |
| Public legal and deletion resources | scoped NAS host/container deploy + anonymous HTTPS render | 개인정보처리방침, 이용약관, 앱 외부 계정 삭제 요청 경로를 기존 사이트 전체와 분리해 배포했다. host와 running container 4개 파일 SHA 일치; /privacy/, /terms/, /delete-account/ 모두 외부 HTTPS 200·정확한 title, privacy→deletion 링크 visible. 실서버 본문 운영자는 YUN CHAN, Cloudflare email-protection 복호화 연락처는 yunchan8804@gmail.com, TWENTYOZ 잔존은 0건이다. Google Play 정책상 필요한 앱 식별·개발자 문의·수집/공유·보관/삭제·외부 삭제 요청 경로를 포함하고 모바일 Settings/Paywall에도 canonical link를 노출 |
site/public/legal.css, site/public/privacy/index.html, site/public/terms/index.html, site/public/delete-account/index.html, apps/mobile-rn/src/screens/SettingsScreen.tsx, live d3ro.chanpaca.net |
2026-08-21 |
| Android upload signing identity | create-only 3072-bit RSA PKCS12 + Windows credential vault + certificate readback | 2026-08-21에 생성한 local upload-key 후보 SHA-256은 4F:AC:69:24:82:1C:50:DA:AB:ED:76:49:32:A5:3C:48:6F:8C:6C:5F:34:B9:F1:8D:B9:20:AA:40:99:15:2B:54다. 다만 production CI secret·오프라인 복구 백업·실제 AAB signer 증거는 없다. Play Console upload certificate는 첫 AAB 업로드 후 표시되며, 현재 확인한 Play app-signing SHA-256과 분리해 대조해야 한다 |
release/android-release-identity.json, scripts/gen-keystore.js, Windows Credential Manager |
2026-08-29 |
| Release evidence signing identity | Ed25519 keypair creation + public-key fingerprint + sign/verify roundtrip | private key는 C:\Users\encep\.d3ro\release\d3ro-mobile-evidence-ed25519-private.pem user-only ACL, public key는 release/mobile-release-evidence-public.pem이다. keyId 2797d3e63affd2348941bc2871b57e520c958f7f5da1a4bbe8aa46904a890b7f, pair/roundtrip GREEN. CI private-key secret·오프라인 복구 백업·실제 signed evidence는 대기 |
release/mobile-release-evidence-public.pem, release/android-release-identity.json, scripts/ci/verify-release-evidence-key-pair.mjs |
2026-08-29 |
| Firebase project readiness | Firebase Console u/0, u/1 live 확인 |
두 계정 모두 D3RO project가 없다. production project·Android app·google-services.json·FCM은 사용자 승인 후 새로 준비해야 한다 |
Firebase Console, apps/mobile-rn/android/app |
2026-08-29 |
| AdMob production identity | live console + release identity exact match | app ca-app-pub-1039714767792854~6427959892, banner ca-app-pub-1039714767792854/9840591290, rewarded ca-app-pub-1039714767792854/2255790918는 일치한다. 그러나 검토 필요, 광고 게재 제한, store 미연결, 결제 프로필 미완료라 production 게재 GREEN이 아니다 |
release/android-release-identity.json, AdMob live console |
2026-08-29 |
| Production Supabase deployment | linked migration/function deploy + live AdMob probes | remote migration 00001~00028이 local과 일치하고 admob-ssv v13이 ACTIVE다. rewarded unit secret 존재, unsigned missing-query는 200, unknown key는 503, AdMob URL verification은 GREEN이다. 00028 전후 schema dump는 각각 SHA-256 92CAA70E…A1DF, 7545ADD2…EB4E로 보존했다. Stripe/Play/Resend/STT/FCM provider gates와 실제 Google-signed reward 지급 E2E는 남음 |
scratch/production-backups/admob-ssv-before-20260821000028-20260824.sql, scratch/production-backups/admob-ssv-after-20260821000028-20260824.sql, server/supabase/migrations/20260821000028_ad_reward_receipt_replay_protection.sql, server/supabase/functions/admob-ssv |
2026-08-24 |
| Production DB credential | linked schema dump + Supabase CLI source audit | CLI db dump --dry-run이 credential을 stdout에 출력하지만, CLI 공식 소스 대조 결과 primary DB password가 아니라 API가 매 작업마다 생성하고 만료시키는 cli_login_postgres 임시 역할 password다. primary rotation은 불필요하며 저장소·Supabase trace 잔존 0. 해당 dry-run 명령은 credential 출력 때문에 재사용 금지 |
Supabase CLI internal/utils/flags/db_url.go, scratch/prod-public-schema-before-mobile-20260821.sql |
2026-08-21 |
| Physical Fold6 | exact .11 APK Taildrop→z-fold6 |
TRANSFERRED over active direct Tailnet; D3RO-Voice-0.0.0-e2e.20260821.11-TEST-DEMO-74035b69db0a.apk, 146,739,935 B, SHA-256 74035B69DB0A564846DF5ED4B85CA5D0E2289D5BB7D73DEE02C35DFD57380C2B. 실제 기기 설치·실행·OAuth·구매는 사용자 확인 PENDING |
Fold6 Taildrop/runtime | 2026-08-21 |
| Mobile secure auth/account | secure storage·logout·recording cleanup·identity linking Jest | Keychain strict response 검증, legacy migration, local purge, remote sign-out 실패 fallback, recorder/queue cleanup, provider link/unlink 안전장치 GREEN. 최신 APK logout/delete/provider E2E는 PENDING | apps/mobile-rn/src/lib/secure-auth-storage.ts, apps/mobile-rn/src/lib/logout.ts, apps/mobile-rn/__tests__ |
2026-08-21 |
| Mobile admin E2E | ordinary/manager/admin/super_admin/stale-manager API 34 journeys | 55 assertions PASS. Free test 광고 표시·관리 request 0, Pro 광고 미요청, manager 구독 credits/memo 수정, admin bounded role+delete confirm/cancel, super manager→admin, stale JWT 즉시 403와 target/modal purge. auth/profile/operation/audit fixture 0 | apps/mobile-rn/.maestro-output/admin-local/evidence-role-e2e-pass.json, admin-local-ordinary-free-ad-visible.png, admin-local-admin-bounded-role-options.png, admin-local-stale-manager-forbidden-purged.png |
2026-08-21 |
| Android incoming share | main/androidTest Kotlin compile + API 34 instrumentation + external provider E2E | 허용 MIME만 수신, UI thread 밖 provider I/O, size/name/type cap, provider 예외·unsupported/empty/oversize·비 AAC MP4 fail-closed 구현. slow provider 비차단, provider SecurityException, unsupported video one-shot failure 3/3 GREEN. 별도 UID ContentProvider APK의 WAV를 ACTION_SEND해 Record 라우팅, app-owned cache copy, retry queue, cancel cleanup까지 GREEN; canonical cache path와 RN cache alias 불일치도 실제 E2E에서 발견·교정 |
apps/mobile-rn/android/app/src/main, apps/mobile-rn/android/app/src/androidTest, apps/mobile-rn/.maestro/incoming-share-local-check.yaml, scripts/ci/run-mobile-incoming-share-local-e2e.ps1 |
2026-08-21 |
| Emulator recorder | 권한→FGS 녹음→HOME→통화 focus loss→resume→SIGKILL→cold recovery→discard | GREEN, 실제 WAV 성장/header/journal/notification cleanup 확인 | API 34 emulator-5554 logcat + 앱 DB/cache inspection |
2026-08-21 |
| Emulator STT/Talk | 실제 Korean WAV/import→STT→history/share, PTT WAV→STT→Claude SSE→TTS/stop | GREEN; cloud provider 미구성은 503 fail-closed, local Whisper fallback은 인증 우회 없이 동작 | API 34 emulator-5554, public Supabase rows |
2026-08-21 |
| Auth live | production /auth/v1/settings, Google authorize canonical redirect, disposable email login/logout/delete |
Email·Google provider entry GREEN; settings는 Google=true/GitHub=false/Apple=false, Google authorize 302→accounts.google.com, Supabase canonical callback·state/client ID present. full Google consent→mobile callback와 GitHub/Apple은 PENDING |
production Supabase + API 34 emulator | 2026-08-21 |
| Billing test | restore/provider/entitlement unit+hook integration | 3 suites / 28 tests GREEN; sideload는 storeInstallRequired fail-closed. Play license test는 EXTERNAL |
apps/mobile-rn/__tests__/billing*.test*, entitlement.test.ts |
2026-08-21 |
| Ads test | Free Google test banner→rewarded 완주 + production 콘솔/SSV 연결 | 공식 Test Ad banner/AdActivity/Reward granted 실측과 미구성 시 fail-closed를 유지한다. production ID, 50 cloud_ai_tokens, secret, verified SSV URL, Edge v13, receipt exactly-once는 운영 반영했다. production 광고를 클릭하지 않았으며 test-device 실제 Google-signed reward E2E는 남음 |
scratch/demo/d3ro-mobile-test-ad.png, d3ro-mobile-rewarded-test-ad.png, server/supabase/functions/admob-ssv, AdMob live console |
2026-08-24 |
| Admin live-local | login→JWT proxy→role/subscription/audit + stale-role | .NET 21/21, migration 25, Edge/JWT 47 assertions, TLS Chromium console/5xx 0 | scratch/admin-browser-e2e.png |
2026-08-21 |
| STT fail-closed quota | Deno/.NET contracts + 00026 SQL/REST concurrency | provider 전체 실패 502/503, direct legacy user 410, internal exact service token only. 20 concurrent remaining-base 요청에서 exactly 1 reserve, replay single charge, 3 overage exact, provider failure refund, authenticated ledger/RPC denial, fixture 0 | server/supabase/functions/stt-proxy, apps/api-server/Controllers/SttController.cs, server/supabase/migrations/20260821000026_stt_quota_reservations.sql, apps/mobile-rn/__tests__/stt-quota.local.integration.mjs |
2026-08-21 |
| Desktop payment·ads | authenticated Edge-only checkout/subscription readback + no-fill·위조 event·reward·settlement 경계 | 임의 provider/tier/URL, 무조건 성공 verify, legacy local license 우회를 제거하고 timeout·retry idempotency를 fail-closed로 검증. 광고 20/20, 전체 desktop 590 tests, typecheck/build/scoped lint GREEN; 실제 production provider 결제 E2E는 외부 게이트 | apps/desktop/src/main/ipc/payment-handlers.ts, apps/desktop/tests/unit/payment-handlers.spec.ts, scratch/demo/d3ro-desktop-ads-fail-closed.png |
2026-08-21 |
| Credential gate | repository runtime secret scan + release-keystore audit + API fail-closed bootstrap | 평문 keystore password를 포함하던 untracked 생성 스크립트를 발견해 환경변수·PKCS12·create-only로 교체하고 scanner에 keytool literal negative case 추가. 노출된 키는 live direct APK cert 06:EE:…:E4:81과 동일해 d3ro-release-key.COMPROMISED-20260821.keystore로 보존 격리했으며 active path에서 제거. scanner self-test/전체 scan, .NET 26/26, script syntax GREEN |
scripts/gen-keystore.js, scripts/ci/check-no-hardcoded-secrets.mjs, .github/workflows/ci.yml |
2026-08-21 |
| Exact-APK cold launch | fresh uninstall/install→am start -W→top activity/logcat |
GREEN; exact .11 SHA-256 74035B69…380C2B fresh install, LaunchState:COLD, total 0.872초, MainActivity top-resumed. fresh auth·signup·invite PASS, fatal/ANR/React fatal 0 |
API 34 emulator-5556, installed package inspection + Maestro + logcat |
2026-08-21 |
| Exact-APK Maestro E2E | exact .11 TEST-DEMO fresh install + auth/signup/invite, 직전 .9 small-screen journey |
.11 GREEN: fresh-install-auth 30s, fresh-install-signup 40s, invite warm listener+cold getInitialURL 14s. 동일 UI .9의 320x568dp signup 2m39s PASS. .11 전체 구간 fatal/ANR/React fatal 0 |
apps/mobile-rn/.maestro/*.v11.junit.xml, apps/mobile-rn/.maestro-output, apps/mobile-rn/.maestro-output/final-20260821-9 |
2026-08-21 |
| Android instrumentation | API 34 connectedDebugAndroidTest |
4 tests, failures 0, errors 0: CSPRNG 1 + incoming share 3 GREEN | apps/mobile-rn/android/app/build/outputs/androidTest-results/connected/debug/TEST-Pixel_7_API_34(AVD) - 14-_app-.xml, apps/mobile-rn/android/app/build/reports/androidTests/connected/debug |
2026-08-21 |
8. 종료 감사
최종 종료 전 아래 검색과 대조를 수행한다.
apps/mobile-rn/src에서TODO,placeholder, mock 성공, 무반응 handler, 고정 사용자 데이터가 0건인지 확인한다.- 데스크톱 navigation·service 목록, Web route 목록, 본 문서 F/H/T 항목을 다시 대조한다.
- 모든
Pressable,PhysicalButton, switch, 링크가 정상·disabled·오류 상태를 갖는지 검사한다. - 모든 Supabase query에 사용자/RLS 경계와 pagination/error 처리가 있는지 검사한다.
- 결제·광고 보상은 서버 검증 전에 entitlement/토큰을 바꾸는 경로가 0건인지 검사한다.
- 에뮬레이터를 초기화한 clean install과 기존 사용자 upgrade install을 모두 검증한다.
- 실제 설치 APK의 version/signature/hash와 화면에 표시된 버전을 대조한다.