# Google Play 출시 체크리스트 기준일: 2026-08-29. 체크 표시는 이 문서를 읽은 사람이 실제 증거를 확인한 뒤에만 바꾼다. 소스 검사, debug/E2E APK, HTTP 200 하나만으로 release GREEN을 선언하지 않는다. ### 2026-08-29 Play Console live 스냅샷 | 항목 | 확인된 현재 사실 | 판정 | |---|---|---| | 앱 | `D3RO Voice`, package `com.d3ro.voice`, app ID `4976102237698469110` | 생성 완료 | | Console 상태 | `임시`; 첫 AAB 업로드 0건, 설정 0/11 | 제출 불가 | | release identity | versionName `1.1.0`, Android versionCode `1010001` | 소스 SSOT에서 확정; AAB 증거는 아직 없음 | | Play app-signing 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` | Console 실확인 | | upload key | 외부 PKCS12·user-only ACL·Credential Manager·private-key readback GREEN; cert 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` | local key 준비. Console 표시·AAB signer 대조는 첫 AAB 후 | | release evidence | Ed25519 keypair roundtrip GREEN; public key·keyId `2797d3e63affd2348941bc2871b57e520c958f7f5da1a4bbe8aa46904a890b7f` SSOT | CI private-key secret·복구 백업 미완료 | | Firebase | Google Console `u/0`, `u/1` 모두 D3RO project 없음 | 프로젝트·Android 앱 생성은 사용자 승인 필요 | | closed test | 0명 / 요건 12명, 연속 14일 | 미시작 | | production access | disabled | closed test와 access 신청·승인 전까지 출시 불가 | 외부 법적·정책 선언은 일반적인 배포 지시로 대신하지 않는다. Console의 실제 문구를 사용자가 검토하고 action-time 승인하기 전에는 저장·제출하지 않는다. ## P0 — 현재 제출 차단 요약 - [x] 사용자 본인이 Play 개발자 정책과 미국 수출법 선언을 검토·승인하고 앱 생성을 실행했다: app ID `4976102237698469110`. - [ ] AI 생성 결과의 인앱 신고와 운영 moderation 원장이 production에서 E2E 검증됐다. - [ ] 개인정보처리방침에 AdMob 자동 데이터와 AI/UGC 신고 데이터가 구체적으로 반영됐다. - [x] 기본 Android Studio launcher icon을 D3RO legacy/adaptive/monochrome icon source로 교체하고 512×512 Play icon을 만들었다. - [x] JDK 17 양 ABI debug build와 기존 데이터 보존 update install 후 Pixel Launcher emulator의 adaptive circle mask를 확인했다. - [ ] Play-signed release 설치본과 실제 Pixel/Samsung 등 OEM mask·monochrome scale을 확인했다. - [x] 1024×500 feature graphic 후보 4개와 SVG 원본·PNG 해시·재현 절차를 준비했다. - [ ] 사용자 선택 및 Console preview 검증으로 feature graphic 최종본을 확정했다. - [ ] 실제 release 앱 스크린샷을 준비했다. - [x] Console에서 Play app-signing certificate SHA-256을 확인했다. - [ ] 첫 AAB 업로드 후 Console이 표시하는 upload certificate가 준비한 key의 SHA-256과 일치하고 Play app-signing certificate와 다름을 증명했다. - [ ] source `assetlinks.json` 3개는 Play app-signing certificate로 교체했지만 live는 아직 구 certificate다. 같은 소스를 배포하고 public HTTPS 응답을 재검증한다. - [ ] Firebase production 프로젝트/Android 앱/`google-services.json`과 Play app-signing fingerprint를 연결했다. - [ ] production secrets로 signed AAB를 만들고 package/version/config/signature/ABI/16 KB page size를 검증했다. - [ ] Play internal track에서 **Play가 서명한 설치본**으로 광고, 결제, FCM, App Links, 녹음 FGS, AI 신고, 계정 삭제를 실기기 E2E 검증했다. - [ ] reviewer용 Free와 Pro+ 재사용 계정, FGS 영상 URL, Data safety 최종 답을 Console에 입력했다. - [ ] 현재 확인된 요건대로 12명을 모집해 연속 14일 closed test를 완료하고 production access를 승인받았다. 현재 0명이고 access는 disabled다. ## 1. 개발자 계정과 앱 생성 ### 확인된 준비값 | 항목 | 값 | 상태 | | -------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------- | | Google 계정 | `yunchan8804@gmail.com` | live handoff에서 확인. 제출 직전 account switcher 재확인 | | 개발자 | `YUN CHAN` | 개인 개발자 계정 | | 개발자 계정 ID | `7374613349497835192` | live handoff 값. Console URL/계정 화면 재확인 | | 앱 이름 | `D3RO Voice` | 생성 완료 | | package | `com.d3ro.voice` | 생성 시 사용 가능 확인 후 등록 | | 기본 언어 | 한국어 (`ko-KR`) | 생성 완료 | | 유형 | 앱 | 생성 완료 | | 가격 | 무료 | 생성 완료. 무료 앱은 나중에 유료 다운로드 앱으로 전환할 수 없다는 경계를 이해하고 선택 | | 정책·수출법 checkbox | 선택 완료 | 사용자 action-time 확인 후 생성 | | `앱 만들기` | 실행 완료 | app ID `4976102237698469110`. Chrome에서 생성 후 대시보드 확인 | | 자동 보호 | Console 기본 활성 상태로 보였으나 결정하지 않음 | release 영향 검토 후 사용자 결정 | ### 실행 체크 - [ ] account switcher에서 이메일·개발자명·계정 ID를 화면 캡처했다. - [ ] Policy status에 계정 issue가 없는지 재확인했다. - [ ] Android developer verification/패키지 등록 상태를 새 앱 생성 후 재확인했다. - [x] Dashboard에서 production access가 disabled이고 12명·14일 closed-test 요구사항이 적용됨을 확인했다. - [ ] 새 개인 계정에 기기 확인 요구가 나타나면 Android 10+의 root되지 않은 실제 기기에서 Play Console 모바일 앱으로 완료했다. - [x] 사용자에게 정책·수출법 선언의 정확한 문구와 현재 사실을 보여주고 action-time 승인을 받았다. - [x] 사용자 승인 후에만 두 checkbox와 `앱 만들기`를 실행했다. - [x] 앱 생성 직후 package/name/default language/developer를 다시 기록했다: app ID `4976102237698469110`, `D3RO Voice`, `com.d3ro.voice`, `ko-KR`, `YUN CHAN`. - [ ] 자동 보호의 장점·디버깅/비Play 배포 영향 검토 후 release별 설정을 기록했다. 기본값을 무심코 변경하지 않았다. 공식 기준: [앱 생성](https://support.google.com/googleplay/android-developer/answer/9859152?hl=en), [새 개인 계정 기기 확인](https://support.google.com/googleplay/android-developer/answer/14316361?hl=en). ## 2. 저장소·릴리스 원본 확정 - [ ] mobile productization 전체가 권위 있는 commit에 포함됐고 `origin/main` 또는 합의한 release branch에 push됐다. - [ ] dirty/untracked 파일을 그대로 release source로 쓰지 않았다. - [ ] unrelated 사용자 변경을 reset/clean/덮어쓰기 하지 않았다. - [ ] release commit SHA와 tree hash를 기록했다: ``. - [ ] CI가 실제 연결된 remote에서 해당 SHA를 checkout했음을 증명했다. - [ ] `.github/workflows/release.yml`의 Android job은 현재 GitHub Actions용이지만 저장소 remote는 GitLab/Forgejo다. 실행 가능한 GitHub private repository/runner가 실제로 연결되기 전에는 workflow 존재만으로 CI GREEN을 선언하지 않았다. - [ ] 대안 CI를 사용한다면 release-only secrets, 동일 검증 스크립트, 제한된 AAB handoff와 provenance를 동등하게 구현했다. - [ ] 과거 self-hosted `com.d3rovoice` APK, debug signer, TEST-DEMO APK를 Play artifact로 재사용하지 않았다. - [x] desktop offline license는 mobile evidence key와 분리된 새 Ed25519 keypair를 사용하고, public SSOT `apps/desktop/resources/license/production-public.pem`의 keyId `5c52b765135ee2531c681b53cd4dc0e96fff8737f496c0b04ba8334fc81a887f`를 release metadata gate가 검증한다. - [ ] desktop offline license를 운영한다면 외부 private key를 admin `ADMIN_LICENSE_PRIVATE_KEY` secret로 주입하고 실제 발급→desktop 활성화 roundtrip을 별도 검증했다. 이 항목은 Play AAB 서명/evidence key와 절대 공유하지 않는다. ## 3. Play App Signing·Firebase·App Links ### 인증서 경계 - [x] Console에서 Play app-signing certificate를 확인했다. - [x] upload key `C:\Users\encep\.d3ro\release\d3ro-upload-key-20260821.p12` / alias `d3ro-upload-20260821`이 저장소 밖 user-only ACL로 보관되고 Credential Manager target이 존재하며 private-key readback이 GREEN임을 확인했다. - [x] upload key certificate가 알려진 폐기 certificate와 다름을 확인했다. 실제 AAB signer 사용 증거는 아직 없다. - [x] local upload certificate 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` - [ ] 첫 AAB 업로드 후 Console에 표시된 upload certificate가 위 local certificate와 일치한다. - [x] Play app-signing certificate 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 app-signing certificate SHA-1: `` - [x] local upload certificate와 Play app-signing certificate의 SHA-256이 다름을 확인했다. 첫 AAB 후 Console upload certificate로 재확인한다. - [ ] CI의 AAB signer 검증에는 upload SHA-256을 사용했다. - [ ] Firebase OAuth, Google sign-in과 HTTPS App Links에는 **Play app-signing** SHA-1/SHA-256을 등록했다. **현재 blocker:** `site/public`, `apps/web/public`, `apps/api-server/wwwroot`의 source `assetlinks.json` 3개는 확인된 Play app-signing SHA-256으로 교체했다. 그러나 live `https://d3ro.chanpaca.net/.well-known/assetlinks.json`은 아직 폐기된 과거 certificate를 반환하므로 배포와 public 재검증이 필수다. upload certificate는 `assetlinks.json`에 넣지 않는다. 코드 경계: `.github/workflows/release.yml`은 `ANDROID_UPLOAD_CERT_SHA256`과 `ANDROID_PLAY_APP_SIGNING_CERT_SHA256`을 분리하고, `scripts/ci/mobile-release-evidence-lib.mjs`와 App Links verifier가 폐기 certificate를 거부해야 한다. ### Firebase - [x] Firebase Console `u/0`, `u/1`을 재확인했고 두 계정 모두 D3RO project가 없음을 확인했다. - [ ] 사용자 action-time 승인 후 올바른 Google 계정에서 production Firebase project를 만들거나 명시적으로 선택했다: ``. - [ ] Android 앱 `com.d3ro.voice`를 등록했다. - [ ] Play app-signing SHA-1/SHA-256을 Firebase Android 앱/OAuth client에 등록했다. - [ ] production `google-services.json`을 CI secret으로 저장했다. 로컬/저장소에는 남기지 않았다. - [ ] FCM sender/project가 Supabase production push 설정과 일치한다. - [ ] Google OAuth redirect/deep link가 canonical `d3ro-voice://auth-callback`과 실제 Supabase/Firebase 설정에 일치하며, 폐기한 `d3ro://` scheme은 export되지 않는다. - [ ] `https://d3ro.chanpaca.net/.well-known/assetlinks.json`이 Play app-signing fingerprint를 제공한다. - [ ] Play 설치본에서 `adb shell pm get-app-links com.d3ro.voice`와 실제 invite URL 진입이 GREEN이다. [Play App Signing 공식 설명](https://support.google.com/googleplay/android-developer/answer/9842756?hl=en)에 따라 upload key와 app-signing key를 구분한다. ## 4. Production AAB 생성과 정적 검증 ### 빌드 입력 - [x] 소스는 compile/target API 36, min API 24를 선언한다: `apps/mobile-rn/android/build.gradle:21-25`. - [x] package는 `com.d3ro.voice`: `apps/mobile-rn/android/app/build.gradle:289-302`. - [x] release cleartext traffic은 false이고 release ABI는 arm64-v8a: `build.gradle:372-386`. - [x] release gate는 keystore, version, Firebase config, production AdMob app/banner/rewarded ID를 요구한다: `build.gradle:45-103,157-219`. - [x] release identity를 `D3RO_VERSION_NAME=1.1.0`, `D3RO_VERSION_CODE=1010001`로 확정했다. - [x] Ed25519 release-evidence keypair을 생성하고 private key를 저장소 밖 user-only ACL 경로에, public key를 `release/mobile-release-evidence-public.pem`에 보존했다. keyId `2797d3e63affd2348941bc2871b57e520c958f7f5da1a4bbe8aa46904a890b7f`, sign/verify roundtrip GREEN이다. - [ ] upload/evidence private key·Firebase·AdMob secrets를 승인된 CI secret store에 주입하고 별도 복구 백업을 검증했다. ### 산출물·검증 - [ ] `:app:bundleRelease -PreactNativeArchitectures=arm64-v8a`로 `app-release.aab`를 만들었다. - [ ] AAB SHA-256: `` - [ ] build source SHA: `` - [ ] package/versionName/versionCode/targetSdk/minSdk가 기대값과 일치한다. - [ ] AAB signer가 upload certificate와 일치하고 debug/폐기 certificate가 아니다. - [ ] embedded BuildConfig는 production Supabase/Firebase/AdMob ID이며 Google test AdMob publisher가 아니다. - [ ] `android:debuggable=false`, `usesCleartextTraffic=false`를 확인했다. - [ ] arm64 native library만 delivery되고 각 native dependency의 license를 보존했다. - [ ] bundled Whisper model의 size/SHA가 gate 기대값과 일치한다. - [ ] AAB, 검증 JSON, signed evidence, SHA256SUMS를 변경 불가능한 release record로 보관했다. - [ ] AAB는 제한된 Play Console handoff artifact로만 제공하고 public release/site에 upload-key APK/AAB를 게시하지 않았다. 현재 작업공간의 `apps/mobile-rn/android/app/build/outputs/bundle/release/app-release.aab`는 존재하지 않는다. 기존 release APK나 E2E APK를 이 항목의 증거로 인정하지 않는다. ### 16 KB page size — 필수 blocker D3RO Voice는 React Native/Whisper 등 native library를 포함하고 NDK r27.1을 지정하므로 source 설정만으로 호환을 가정하지 않는다. - [ ] `bundletool dump config --bundle=` 결과가 `PAGE_ALIGNMENT_16K`다. - [ ] AAB에서 생성한 APK set의 모든 `.so` ELF segment alignment와 zip alignment를 공식 도구로 확인했다. - [ ] Play pre-launch report에 16 KB page-size incompatibility가 없다. - [ ] Android 15+ 16 KB emulator 또는 실제 16 KB 기기에서 clean install/cold start, 녹음, local Whisper transcription, Talk, 결제 SDK 초기화, 광고 SDK 초기화가 GREEN이다. - [ ] native crash/UnsatisfiedLinkError가 없고 로그를 보존했다. 공식 기준: [16 KB page size 지원](https://developer.android.com/guide/practices/page-sizes). API 36은 2026-08-31부터 새 앱/업데이트 요구사항이며 현재 소스 설정은 이를 충족하지만 AAB 업로드 결과로 다시 확인한다: [Target API](https://support.google.com/googleplay/android-developer/answer/11926878?hl=en). ## 5. 스토어 등록정보와 자산 - [ ] [`01-store-listing.md`](01-store-listing.md)의 ko-KR/en-US 제목·설명을 실제 release 기능과 대조했다. - [ ] category `Productivity`와 실제 제공되는 태그만 선택했다. - [ ] 지원 이메일의 수신·응답을 확인했다. - [ ] privacy/terms/delete URL이 익명 모바일 브라우저에서 HTTPS 200, 올바른 title/본문, no-login이다. - [ ] root website가 유효한 지원 사이트가 아니면 website 필드를 비워 뒀다. - [x] 기본 Android robot launcher icon을 제거했다. - [x] adaptive icon foreground/background/monochrome와 legacy density icon을 같은 canonical D3RO artwork로 만들었다. - [x] Pixel Launcher emulator의 adaptive circle mask를 캡처했다: `docs/v3/play/assets/proof/d3ro-icon-pixel-launcher-20260824.png`, SHA-256 `7A2DA876FBFD54089B783A7FD45C2472476ED47DCEABA08AB305B7B01A18D430`. - [ ] Play-signed release를 실제 Pixel/Samsung 등 OEM 기기에 설치해 icon scale·safe zone·monochrome를 캡처했다. - [x] Play icon 512×512 PNG를 생성했다: `docs/v3/play/assets/d3ro-voice-play-icon-512.png`. - [ ] Console upload 후 alpha/모서리/안전 영역 경고가 없는지 확인했다. - [x] feature graphic 1024×500 후보 4개와 재현·해시 기록을 준비했다: `docs/v3/play/assets/feature-graphic/`. - [ ] 후보 중 최종본을 사용자 선택 후 Console preview에서 검증했다. - [ ] phone screenshot 최소 2장, 권장 4장 이상을 실제 Play release 설치본에서 1080×1920급으로 캡처했다. - [ ] 녹음, 전사 결과, Talk+신고, 회의/팀, 개인정보/삭제처럼 실제 핵심 기능을 보여준다. - [ ] reviewer credential, 실사용자 이메일, 토큰, 실제 전사·회의 내용을 screenshot에 넣지 않았다. - [ ] 로그인/초대 경계 E2E screenshot을 기능 대표 store asset으로 재사용하지 않았다. ## 6. 개인정보·Data safety·법적 문서 - [x] Settings에서 privacy, terms, account deletion URL을 연다: `apps/mobile-rn/src/screens/SettingsScreen.tsx:472-493`. - [x] 가입 동의 영역에서 terms와 privacy를 각각 열 수 있다: `apps/mobile-rn/src/screens/SignUpScreen.tsx:326-369`. - [x] 앱 내 계정 삭제 성공 후 계정 범위 로컬 데이터를 purge한다: `AccountScreen.tsx:410-455`, `account-local-data.ts:21-49`. - [x] 공개 legal/deletion URL은 2026-08-24 mount 복구 후 외부 HTTPS 200이 확인됐다. 제출 직전 재검증한다. - [ ] privacy 문서가 AdMob의 IP 기반 대략적 위치, 앱 상호작용, 진단, 광고/기기 ID와 광고·분석·사기 방지 목적을 명시한다. - [ ] privacy/terms가 AI·UGC 신고 데이터, 금지 콘텐츠, 검토·조치, 보관·삭제를 반영한다. - [ ] [`02-data-safety-draft.md`](02-data-safety-draft.md)의 모든 `검증 필요`를 release/provider 증거로 해소했다. - [ ] Console Data safety preview와 공개 privacy 문서를 한 줄씩 대조했다. - [ ] 계정 삭제 URL, 앱 내 경로와 제한 보관 항목을 Console에 정확히 답했다. ## 7. AI·UGC 정책 gate - [x] `X-D3RO-Generation-Purpose`/`X-D3RO-Generation-Id`, 30일 generation receipt와 `talk_response|command_response|action_response` source contract가 구현됐다. - [x] 신고 backend의 authenticated reporter, generation receipt/target allowlist, reason allowlist, comment/snapshot 길이 제한, rate limit, RLS, idempotency와 감사 상태가 구현됐다. - [x] 일반 사용자의 `profiles.role` self-promotion과 `profiles.tier` self-assignment를 column ACL로 차단하고 public profile 필드 수정은 유지했다. - [x] local SQL integration, HTTP Edge 15 assertions와 shared Deno 64 tests가 GREEN이다. - [x] disposable local Supabase Gateway→Edge→DB Red E2E 650개가 GREEN이다: [`../e2e/RED_E2E_500_CONTENT_REPORT.md`](../e2e/RED_E2E_500_CONTENT_REPORT.md). - [x] pending→reviewing→dismissed/actioned 흐름, 해결 후 180일 `evidence_expires_at`, account deletion identity unlink와 service-only purge RPC가 구현됐다. - [ ] Talk와 모든 생성 문서 결과에서 인앱 신고 UI가 있다. - [ ] AI 결과가 restricted content를 생성하지 않도록 provider safety/filter와 서버 정책을 검증했다. - [ ] Play release 설치본에서 신고 sheet가 첨부될 AI 응답을 미리 보여주는지 확인했다. 제출 시 선택된 AI 응답 snapshot만 포함하며 음성·전체 대화·원래 prompt는 자동 복사하지 않는다. - [ ] generation receipt에 raw prompt/전체 생성 결과가 없고 Edge/general audit log에 신고 snapshot 원문이 없는 것을 production log로 재확인했다. - [x] moderation SLA·escalation·삭제/보관·purge·감사 runbook 초안을 만들었다: [`05-content-reporting-operations.md`](05-content-reporting-operations.md). - [ ] 자동 purge scheduler, 실제 운영 담당과 실패 알림을 runbook에 연결했다. - [x] 30일 receipt, 해결 전 evidence, 해결 후 180일, 계정 삭제 identity unlink와 purge를 privacy/terms 로컬 초안에 반영했다. - [ ] privacy/terms 로컬 초안을 법률 검토 후 공개 배포하고 익명 모바일 브라우저에서 재검증했다. - [ ] 운영 moderation 책임자·on-call을 실제 사람으로 지정했다. - [ ] migration `20260824000029`, `content-report`/`llm-proxy` function과 모바일 신고 UI를 같은 production release에 배포했다. - [ ] 신고 제출→관리 검토 원장 도달→상태 변경까지 production E2E가 GREEN이다. - [ ] 초대 팀 외부로 데이터가 노출되지 않는 RLS/ACL을 검증했다. - [ ] reviewer instructions에 신고 경로가 영어로 정확히 적혀 있다. 이 gate가 RED이면 생성형 AI 기능이 central feature인 현재 앱을 제출하지 않는다. [AI-Generated Content 정책](https://support.google.com/googleplay/android-developer/answer/13985936?hl=en). ## 8. Google Play Billing과 merchant - [x] 코드 상품 ID는 `d3ro_voice_pro_monthly`, `d3ro_voice_pro_plus_monthly`: `apps/mobile-rn/src/lib/billing-context.tsx:32-35`. - [x] 현재 local resolved dependency evidence는 Play Billing Library 9.1.0이다. production Gradle dependency report로 재확인한다. - [x] PBL 9는 2028-08-31까지의 현재 신규 앱/업데이트 지원 창에 있으며, 2026-08-31에 종료되는 PBL 7 경계를 넘는다. 최종 AAB manifest의 `com.google.android.play.billingclient.version`으로 다시 증명한다: [PBL deprecation timeline](https://developer.android.com/google/play/billing/deprecation-faq). - [x] 구매는 서버 `iap-verify` 검증과 entitlement snapshot 확인 후 성공 처리하는 경계가 있다. - [ ] Google Play payments/merchant profile을 올바른 법적 개인·국가·세금 정보로 완료했다: ``. - [ ] 두 subscription과 base plan/offer를 Console에 정확한 ID로 만들었다. - [ ] 가격, 결제 주기, 자동 갱신, 무료 체험 여부를 ko/en 구매 화면과 일치시켰다. site 문구만 보고 trial을 생성하지 않았다. - [ ] Google Play Developer API service account와 최소 권한을 설정했다: ``. - [ ] RTDN Pub/Sub push 인증과 production Edge endpoint를 설정했다. - [ ] license tester 계정으로 신규 구매, pending→purchased, 취소, grace/on-hold, upgrade/downgrade, restore, refund/voided purchase를 확인했다. - [ ] purchase token replay/cross-account/package mismatch가 거부된다. - [ ] 계정 삭제가 Play 구독을 자동 취소하지 않음을 앱·웹에서 명확히 안내한다. - [ ] reviewer Pro+ 계정은 실제 결제를 요구하지 않고 review 기간 내 유지된다. ## 9. AdMob·UMP·SSV - [x] `release/android-release-identity.json`과 live Console의 AdMob identity를 대조했다: app `ca-app-pub-1039714767792854~6427959892`, banner `ca-app-pub-1039714767792854/9840591290`, rewarded `ca-app-pub-1039714767792854/2255790918`. - [x] production SSV URL과 rewarded `50 cloud_ai_tokens` 계약을 저장했다. - [ ] AdMob의 `검토 필요`·`광고 게재 제한` 상태를 해소했다. - [ ] AdMob 지급 프로필을 완료했다: ``. - [ ] Play store 등록정보와 AdMob app을 연결하고 app review/approval을 완료했다. - [ ] UMP privacy message를 대상 지역에 publish하고, consent granted/denied/not-required/privacy-options-required를 각각 확인했다. - [ ] Play internal 설치본을 AdMob test device로 등록했다. - [ ] 실제 Google-signed rewarded callback→durable receipt→claim→`+50 cloud_ai_tokens`를 test device에서 E2E 검증했다. - [ ] 중복 transaction, unknown user, cap/cooldown/ineligible, account deletion unlink와 retry가 의도대로 동작한다. - [ ] Pro/Pro+에서 SDK ad request가 발생하지 않는다. - [ ] production 광고를 개발자/테스터가 클릭하지 않았다. AdMob 콘솔 준비를 실제 광고 게재 승인·수입·Play release 완료로 해석하지 않는다. ## 10. App content 선언과 reviewer 자료 - [ ] Ads=`Yes`, Advertising ID=`Yes`를 final merged manifest와 맞춰 저장했다. - [ ] App access에 Free와 Pro+ reusable 계정을 영어로 등록했다. - [ ] 두 계정 모두 OTP/2FA/CAPTCHA/지역 제한 없이 clean install에서 로그인된다. - [ ] Target audience는 18+ only, children appeal은 No로 제품 경계와 일치한다. - [ ] IARC에 ads, digital purchase, generative AI, invited-team UGC/interaction을 숨김없이 답했다. - [ ] Financial features는 내부 quota가 비양도·비환금임을 확인한 뒤 `My app doesn't provide any financial features`로 저장했다. - [ ] account deletion 답변과 공개 URL을 저장했다. - [ ] microphone FGS type/use case/설명/지연 영향과 ``을 입력했다. - [ ] FGS 영상 URL을 로그아웃/익명 창에서 열 수 있다. - [ ] 모든 placeholder를 제거했다. - [ ] [`03-app-content-draft.md`](03-app-content-draft.md)와 Console preview를 최종 대조했다. ## 11. Internal track — Play-signed 실기기 E2E - [ ] AAB를 internal track에 upload하고 processing/error/warning을 모두 검토했다. - [ ] App Bundle Explorer에서 delivered APK의 package/version/target/ABI/permission을 확인했다. - [ ] Play app-signing certificate가 기대값과 일치한다. - [ ] Play internal opt-in link로 실제 기기에 clean install했다. sideload APK로 대체하지 않았다. - [ ] Android 10+ 일반 4 KB 기기와 Android 15+ 16 KB 환경에서 검증했다. - [ ] fresh onboarding→email login→logout→다른 계정 login의 privacy boundary가 GREEN이다. - [ ] email signup, 약관/privacy 링크, OAuth redirect를 검증했다. - [ ] 마이크 허용/거부, notification 허용/거부, FGS background/lock/pause/resume/stop/discard, 통화/오디오 focus interruption을 검증했다. - [ ] cloud STT 정상/timeout/provider 장애→local fallback, offline queue/resume/cancel, low storage/process kill을 검증했다. - [ ] MP3/M4A/AAC/OGG/FLAC/WAV/WebM/MP4 유효 파일과 invalid/oversize/mime mismatch를 검증했다. - [ ] Talk streaming, TTS, AI 신고와 restricted prompt 처리 흐름을 검증했다. - [ ] team invite warm/cold HTTPS App Link, 역할, 제거/탈퇴, RLS를 검증했다. - [ ] FCM 등록·수신·logout detach·계정 삭제 detach를 검증했다. - [ ] Free ads/UMP/rewarded SSV와 Pro+ no-ad를 검증했다. - [ ] Play subscription purchase/restore/cancel 상태를 검증했다. - [ ] export/restore와 계정 삭제 후 서버·로컬 데이터 제거를 검증했다. - [ ] 앱 업데이트에서 데이터/세션/구독을 보존하고 signer lineage가 일치한다. - [ ] Play pre-launch report의 crash, ANR, accessibility, security, permission, 16 KB 문제를 처리했다. ## 12. Closed test와 production access 개인 개발자 계정이 2023-11-13 이후 생성됐다면 production 전에 최소 12명이 closed test에 **연속 14일** opt-in 상태여야 한다. tester가 중간에 opt-out하면 연속 기간이 다시 계산된다. - [x] Console Dashboard에서 12명·연속 14일 요구사항과 production access disabled 상태를 확인했다. - [ ] 적용 시 최소 12명의 실제 tester를 모집하고 개인정보·NDA·피드백 경로를 안내했다. - [ ] tester 목록과 opt-in 시각을 보존했다. - [ ] 14일 동안 crash-free install만 세지 않고 녹음, 전사, AI, 팀, 광고/결제, 삭제 기능을 실제 사용하게 했다. - [ ] 버그·사용성·배터리·권한·광고·AI 안전 피드백과 수정 내역을 보존했다. - [ ] production access 질문에 실제 tester 참여/피드백/수정 내용만 답했다. - [ ] 최소 12명이 신청 순간까지 연속 opt-in 상태임을 Console에서 확인했다. - [ ] production access 승인 전 open testing/production을 사용할 수 있다고 가정하지 않았다. 공식 기준: [새 개인 계정 테스트 요구사항](https://support.google.com/googleplay/android-developer/answer/14151465?hl=en-GB). ## 13. Production 제출·점진 배포 - [ ] internal/closed에서 검증한 **동일 AAB SHA** 또는 정당한 수정 후 새로 전부 검증한 AAB를 사용했다. - [ ] release notes ko/en을 작성했다. - [ ] country/region과 가격·세금·정책 적용 범위를 검토했다. - [ ] device catalog 제외가 기능/SDK 사실에 근거하며 불필요하게 넓지 않다. - [ ] 모든 Console warning과 policy declaration을 검토했다. - [ ] 사용자 본인이 production 제출 버튼과 법적 선언을 action-time 확인했다. - [ ] 첫 production은 staged rollout으로 시작하고 비율·중단 기준을 기록했다. - [ ] Android vitals crash/ANR, FGS/배터리, 결제 RTDN, SSV, 신고 queue, auth/STT/AI provider error를 모니터링한다. - [ ] rollback은 versionCode를 되돌리는 것이 아니라 수정된 더 높은 versionCode로 배포한다. - [ ] 스토어 페이지·설치·로그인·핵심 흐름을 외부 사용자 관점에서 재검증했다. ## 14. 최종 evidence pack 다음 자료가 하나의 release record에서 같은 version/SHA를 가리켜야 한다. - [ ] release commit SHA/tree, CI run URL과 runner identity - [ ] AAB SHA-256, versionName/versionCode, package, target/min API - [ ] upload certificate, Play app-signing certificate SHA-1/SHA-256 - [ ] signed build evidence, dependency report, merged manifest, bundletool/16 KB 결과 - [ ] Play Console app ID, App Signing, App Bundle Explorer, track/review 상태 캡처 - [ ] Firebase app/fingerprint/FCM/App Links 증거 - [ ] Data safety/App content/IARC/FGS preview와 공개 legal page 캡처 - [ ] reviewer 계정 로그인 결과(비밀번호 제외) - [ ] 실제 Play 설치본의 device/OS/build 정보와 기능 E2E 로그·화면 - [ ] Billing/RTDN, AdMob UMP/SSV, AI report moderation의 redacted production 증거 - [ ] closed-test tester 수·연속 기간·피드백과 production access 결과 - [ ] staged rollout과 Android vitals 모니터링 기록 ## 외부 placeholder 레지스트리 | Placeholder | 실제 값 소유 위치 | 완료 조건 | | ----------------------------------------------------------- | ---------------------------- | ---------------------------------------- | | `` | Git remote/CI | 권위 있는 release source SHA | | versionName `1.1.0` / versionCode `1010001` | release SSOT | 확정. 실제 AAB·Console metadata 대조는 대기 | | `` | restricted artifact/evidence | 실제 production AAB hash | | upload SHA-256 `4F:AC:69:24:...:15:2B:54` | external key/Play Console | local 값 확정. AAB signer·Console 표시와 일치 대기 | | evidence keyId `2797d3e6...4a890b7f` | release identity/CI secret | public·roundtrip 확인. private CI secret·복구 백업 대기 | | Play app-signing SHA-1 | Play Console App integrity | SHA-256은 확인. SHA-1·Firebase 대조는 대기 | | `` | Firebase Console | 올바른 계정·package 등록 | | `` | Google Cloud/Play Console | 최소 권한, RTDN/API GREEN | | `` | Google payments/Play Console | 상품 판매 가능, 법적·세금 정보 완료 | | `` | AdMob/Google payments | 지급 profile와 검토 완료 | | reviewer credentials | Play Console App access만 | 24시간 재사용 가능, no OTP | | `` | unlisted video storage | 익명 접근 가능, 실제 release 실기기 영상 | | `` | redacted production evidence | 신고→운영 원장 E2E GREEN |