diff --git a/docs/v3/MOBILE_RELEASE_HANDOFF_2026-08-29.md b/docs/v3/MOBILE_RELEASE_HANDOFF_2026-08-29.md index 5e6983f..2ae74c1 100644 --- a/docs/v3/MOBILE_RELEASE_HANDOFF_2026-08-29.md +++ b/docs/v3/MOBILE_RELEASE_HANDOFF_2026-08-29.md @@ -1,10 +1,15 @@ # D3RO Voice 모바일 출시 핸드오프 — 2026-08-29 +최종 갱신: 2026-08-30 KST. 0~14절은 시간순 증거이며 현재 판정과 재개 순서는 +15절을 우선한다. + ## 0. 결론 **모바일 앱은 아직 출시 가능 상태가 아니다.** Google Play 등록정보의 텍스트, -아이콘, feature graphic 초안은 준비됐지만 production AAB, Firebase Android 설정, -upload signing, Play-signed 설치본, 실제 핵심 기능 E2E, 스토어용 앱 스크린샷이 없다. +아이콘, feature graphic 초안과 Firebase project/Android app/config는 준비됐다. +그러나 Firebase SHA fingerprint와 CI secret materialization, production AAB, +upload-key로 서명된 candidate, Play-signed 설치본, 실제 핵심 기능 E2E, 스토어용 +앱 스크린샷은 없다. 2026-08-29 실제 `1.1.0` debug 앱을 새 Pixel 7 에뮬레이터에서 열어 보니 다음을 확인했다. @@ -15,7 +20,9 @@ upload signing, Play-signed 설치본, 실제 핵심 기능 E2E, 스토어용 - 인증 세션이 없어 녹음·전사·AI·팀 화면에는 진입하지 못했다. - production/Play-signed 설치본이 아니므로 이번 캡처는 Google Play 제출물이 아니다. -사용자 요청에 따라 작업은 여기서 중단했다. `/goal`은 완료로 처리하지 않는다. +2026-08-29에는 사용자 요청에 따라 출시 실행을 중단했다. 이 핸드오프 문서는 +15절의 closeout으로 마무리하되, 제품 출시 자체를 완료 또는 production-ready로 +처리하지 않는다. ## 1. 중단 상태 @@ -26,7 +33,7 @@ upload signing, Play-signed 설치본, 실제 핵심 기능 E2E, 스토어용 | 전용 캡처 AVD | `D3RO_PlayCapture_20260829` 생성됨, `emulator-5556` 종료됨 | | 기존 AVD | `emulator-5554`만 연결 상태로 보존. 기존 `0.0.0-e2e` 데이터는 건드리지 않음 | | Metro | `localhost:8081` listener 없음 | -| 로컬 Supabase | `supabase stop --workdir server` 완료, local data는 Docker volume에 백업됨 | +| 로컬 Supabase | `supabase stop --workdir server` 완료, local Docker volume 보존 | | Android 앱 프로세스 | 전용 `emulator-5556` 종료로 함께 중단 | | Play Console | 더 이상 변경하지 않음. 기본 등록정보 페이지는 초안 상태 | | Firebase | 프로젝트 생성 버튼을 누르지 않음. 신규 Firebase 프로젝트 없음 | @@ -360,6 +367,8 @@ production/Play-signed 재촬영 전에는 참고 증거일 뿐이다. ### P0 — 앱을 먼저 검증한다 +이 절은 2026-08-29의 역사적 계획이다. 현재 실행 순서는 15.5절로 대체됐다. + 1. 아래 `재개 전 사실 확인` 명령을 실행한다. 2. Firebase project/app 생성에 대한 action-time 승인을 다시 받는다. 3. Firebase Android app `com.d3ro.voice`를 등록한다. @@ -444,10 +453,13 @@ npm run release:mobile:boundary 기대 기준: -- 세 Git SHA가 모두 `4872d6f6c50a15104792fb31a97176527c3cd9a2` +- local `HEAD`와 실제 `origin/main`이 일치한다. `chanpaca/main`은 Forgejo + runner/public deploy 복구 전까지 이전 public baseline일 수 있으므로 세 SHA가 + 같다고 가정하지 않는다. - 기존 `emulator-5554` 외 새 캡처 emulator는 자동으로 실행돼 있지 않음 - Metro 8081 listener 없음 -- local Supabase containers 없음 +- D3RO Voice local Supabase containers 없음. 다른 프로젝트의 local Supabase + container는 이 판정에 포함하지 않는다. - release metadata/assets/boundary GREEN ## 8. 캡처 AVD 재개 명령 @@ -561,6 +573,8 @@ Play app-signing 및 upload certificate fingerprint를 명확히 구분해 등 ## 13. 내일 첫 체크포인트 +이 절은 2026-08-29의 역사적 체크포인트다. 현재 실행 순서는 15.5절을 따른다. + 내일은 Play Console부터 만지지 않는다. 다음 순서로 시작한다. 1. Git/프로세스/AVD/local stack 상태 재확인 @@ -717,6 +731,8 @@ Google Play의 현재 공식 요구는 휴대전화 screenshot의 최소 변 320 ### 14.6 현재 재개 순서와 승인 요청 +이 승인 전 순서는 15.5절로 대체됐다. + 1. 위 두 CI 파일과 이 핸드오프 문서의 좁은 commit/push를 승인받는다. 2. Firebase project `d3ro-voice-production` 최종 생성과 Android app `com.d3ro.voice` 등록을 action-time 승인받는다. @@ -735,7 +751,7 @@ release는 이번 감사에서 실행하지 않았다. ## 15. 2026-08-30 승인 후 실행과 production 판정 이 절은 14절 작성 뒤 사용자가 명시적으로 승인한 작업과 병렬 production 감사를 -기록한다. 14절의 승인 전 스냅샷과 충돌하면 이 절을 우선한다. +기록한다. 0~14절의 역사적 또는 승인 전 스냅샷과 충돌하면 이 절을 우선한다. ### 15.1 승인 후 실제로 실행한 것 @@ -746,8 +762,13 @@ release는 이번 감사에서 실행하지 않았다. - `.gitlab-ci.yml` - `scripts/ci/verify-mobile-release-boundary.mjs` - `docs/v3/MOBILE_RELEASE_HANDOFF_2026-08-29.md` -- 실제 `origin/main`도 `1f71cf6faeb209c85b49a0260312897a25cc41d9`로 - 확인했다. unrelated dirty worktree는 stage/reset/clean하지 않았다. +- 후속 audit 결과는 이 핸드오프 문서만 별도 closeout commit으로 반영했다. + 최신 commit은 문서 안에 self-reference로 고정하지 않고 `git rev-parse HEAD`와 + `git ls-remote origin refs/heads/main`의 일치로 확인한다. unrelated dirty + worktree는 stage/reset/clean하지 않았다. +- `origin` push는 성공했지만 최신 commit의 GitLab pipeline ID/job 결과는 + 로그인 전이라 확인하지 않았다. 과거 pipeline `72066`과 local verifier GREEN을 + 최신 CI GREEN으로 재사용하지 않는다. - Firebase production project를 생성했다. - project ID: `d3ro-voice-production` - project number: `1013351450402` @@ -869,6 +890,8 @@ low-RAM 실기기 profiling이 필요하다. ### 15.5 다음 실행 순서 +이 절이 6절, 13절, 14.6절의 이전 순서를 대체한다. + 1. HIGH 인증·계정 삭제·계정 간 local data 경계를 먼저 수정하고 적대적/failure injection 테스트를 추가한다. 2. 개인정보처리방침·Data safety와 실제 audio/cache 흐름을 하나의 계약으로 @@ -888,3 +911,101 @@ low-RAM 실기기 profiling이 필요하다. 위 항목 전에는 공개 출시, production-ready 선언, stable tag/public release, debug/E2E 캡처의 store 제출을 금지한다. + +### 15.6 핸드오프 최종 종료 상태 + +- Android emulator/qemu process: `0` +- ADB emulator serial: 없음. Fold6 wireless ADB endpoint 두 줄은 같은 물리기기다. +- Metro `localhost:8081` listener: `0` +- D3RO Voice local Supabase container: `0` +- 보존된 local volume: + - `supabase_db_d3ro-voice` + - `supabase_storage_d3ro-voice` + - `supabase_edge_runtime_d3ro-voice` +- 별도 stop-state archive: + `D:\workspace\_backups\D3ROVoice\local-supabase-stop-20260830\` +- archive manifest: + `D:\workspace\_backups\D3ROVoice\local-supabase-stop-20260830\MANIFEST.md` +- 세 archive는 source volume을 read-only mount해 만들었고 SHA-256을 기록한 뒤 + 전체 `tar -tzf` listing exit `0`으로 검증했다. +- 캡처 3개의 실파일·화면 내용·SHA-256은 다시 대조해 원장과 일치했다. 다만 + `docs/v3/play/assets/screenshots/`는 여전히 untracked이므로 remote clone에 + 보존된 증거라고 주장하지 않는다. owner가 별도 보존 방식을 결정할 때까지 + local evidence로만 취급한다. +- 전용 `emulator-5556`, Metro, local Supabase를 다시 시작하지 않았다. +- Play 제출, CI secret 변경, legal declaration, stable tag/public release, + Forgejo 재배포는 없다. + +### 15.7 정확한 재개 명령 + +먼저 저장소 루트 PowerShell에서 read-only/current-state 검사를 실행한다. + +```powershell +git status --short +git rev-parse HEAD +git ls-remote origin refs/heads/main +adb devices -l +Get-NetTCPConnection -LocalPort 8081 -State Listen -ErrorAction SilentlyContinue +docker ps --format '{{.Names}}' | Select-String 'supabase_.*d3ro-voice' +firebase projects:list +firebase apps:list ANDROID --project d3ro-voice-production +firebase apps:android:sha:list 1:1013351450402:android:4d9d0f675b12ee09bf477b ` + --project d3ro-voice-production +supabase migration list --linked --workdir server +supabase functions list --workdir server +supabase db push --linked --workdir server --dry-run +``` + +보안 경계 수정 뒤 최소 local regression gate: + +```powershell +npm run security:secrets:test +npm run security:secrets +npm run release:mobile:boundary:test +npm run release:mobile:boundary +npm --prefix apps/mobile-rn run lint +npm --prefix apps/mobile-rn run typecheck +npm --prefix apps/mobile-rn run test:ci +npm --prefix apps/mobile-rn audit --omit=dev +``` + +다음 production backend 변경 명령은 migration/function diff와 대상 project를 +다시 확인하고 **action-time 승인 후에만** 실행한다. + +```powershell +supabase db push --linked --workdir server +supabase functions deploy content-report --workdir server +``` + +GitLab에서는 올바른 Maintainer 계정으로 로그인한 뒤 protected exact `main`의 +manual `mobile-production-release` job만 실행한다. secret file을 local shell에 +복사하지 않는다. job의 전체 명령과 artifact 목록은 `.gitlab-ci.yml`의 같은 job을 +소스 오브 트루스로 사용한다. + +Maintainer artifact를 별도 검증 디렉터리에 내려받은 뒤: + +```powershell +$identity = Get-Content release/android-release-identity.json | ConvertFrom-Json +$product = Get-Content release/product-version.json | ConvertFrom-Json +node scripts/ci/verify-android-artifact.mjs ` + --mode release ` + --apk \app-release.apk ` + --aab \app-release.aab ` + --bundletool ` + --expected-admob-app-id $identity.adMobAppId ` + --expected-upload-cert-sha256 $identity.uploadCertificateSha256 ` + --expected-version-name $product.version ` + --expected-version-code $product.androidVersionCode +Get-FileHash \app-release.apk -Algorithm SHA256 +Get-FileHash \app-release.aab -Algorithm SHA256 +``` + +Play internal upload은 별도 승인 뒤 수행한다. Play가 서명한 Fold6 설치본에서 +installer/version/debuggable/signing identity를 먼저 증명한다. + +```powershell +adb -s shell pm list packages -i com.d3ro.voice +adb -s shell dumpsys package com.d3ro.voice +``` + +그 뒤에만 15.5절의 provider·failure·접근성 matrix와 6장 캡처를 진행한다.