# Free 1.0.0 Pre-Release Hardening Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** 개발 전용 동작과 흔적이 최종 산출물에 노출되지 않도록 자동 차단한 뒤, 무료 `1.0.0` 후보 생성부터 제출 직전 점검까지 완료한다.

**Architecture:** production PWA 자체를 검사하는 순수 정책 함수를 만들고 `release:preflight`와
`release:prepare`가 같은 검사를 호출하게 한다. Android는 소스 manifest가 아니라 실제 release
AAB에서 추출한 manifest와 서명 정보를 검증한다. `Try review demo`는 심사용 합성 데이터 기능으로
유지하지만 실제 API·PC·계정 접근이 없다는 기존 검증을 보존한다.

**Tech Stack:** Node.js test runner, Vite production build, Capacitor 8, Android Gradle Plugin,
bundletool, PowerShell Windows packaging, Firebase 공개 문서

## Global Constraints

- 현재 출시 버전은 source·Windows·Android 모두 `1.0.0`, Android `versionCode`는 `2`다.
- 현재 출시는 무료이며 인앱 결제와 결제 상품이 없다.
- `127.0.0.1:43110`과 `127.0.0.1:43111`은 Windows 로컬 런타임 경계이므로 개발 잔재로 제거하지 않는다.
- Capacitor의 `https://localhost` origin은 네이티브 WebView 보안 origin이므로 허용한다.
- production 산출물에는 개발 우회 버튼·개발자 모드 문구·Vite HMR client·소스맵이 없어야 한다.
- `Try review demo`는 합성 데이터만 사용하고 API, 파일, 자격 증명 또는 명령 실행에 접근하지 않는다.
- 배포, Tailscale 변경, Android 서명, 실기기 설치와 Google Play 제출은 각각 별도 운영자 승인이 필요하다.
- 이 문서는 임시 실행 노트다. 아래 삭제 조건을 만족하는 즉시 삭제한다.

---

### Task 1: production 번들에서 개발자 모드 흔적 제거

**Files:**
- Modify: `apps/pwa/src/features/auth/AuthenticationGate.jsx`
- Modify: `apps/pwa/src/shared/i18n.js`
- Modify: `apps/pwa/src/features/connection/connection-ui.test.js`
- Create: `tools/release-pwa-policy.test.mjs`

**Interfaces:**
- Consumes: Vite의 `import.meta.env.DEV`
- Produces: 개발 빌드에서만 보이는 우회 버튼과 개발 문구가 제거된 production PWA

- [x] `connection-ui.test.js`에서 개발 우회가 반드시 `import.meta.env.DEV` 아래에만 존재함을 유지한다.
- [x] `release-pwa-policy.test.mjs`에서 임시 production build를 만들고 JS·HTML 전체에
  `connection-dev-bypass`, `Continue in developer mode`, `개발자 모드로 계속`이 없다고 단언한다.
- [x] 위 테스트를 실행해 현재 정적 i18n 문구 때문에 실패하는 것을 확인한다.
- [x] `pairing.continueDevelopment` 공용 번역 키를 제거하고 DEV 전용 JSX 분기 안에서만 언어별 문구를 만든다.
- [x] `node --test tools/release-pwa-policy.test.mjs apps/pwa/src/features/connection/connection-ui.test.js`가 통과하는지 확인한다.

### Task 2: 재사용 가능한 production PWA 정책 검사

**Files:**
- Create: `tools/release-pwa-policy.mjs`
- Modify: `tools/release-pwa-policy.test.mjs`
- Modify: `tools/release-candidate.mjs`
- Modify: `tools/release-version.test.mjs`
- Modify: `package.json`

**Interfaces:**
- Produces: `assertProductionPwa({ pwaDir }): Promise<{ files: number }>`
- Produces: `runReleasePreflight(): Promise<void>`
- Produces: `npm.cmd run release:preflight`

- [x] 합성 fixture에 `.map`, `/@vite/client`, `react-refresh`, `connection-dev-bypass`,
  개발자 모드 문구를 각각 넣었을 때 `release_pwa_development_artifact`로 거절하는 테스트를 작성한다.
- [x] 정상 fixture는 허용하고 `127.0.0.1` 및 `https://localhost` 문자열만으로는 거절하지 않는 테스트를 작성한다.
- [x] 테스트를 실행해 정책 함수가 없어서 실패하는 것을 확인한다.
- [x] `assertProductionPwa`가 파일명과 UTF-8 텍스트를 검사하되 파일 내용이나 로컬 경로를 오류에 포함하지 않도록 구현한다.
- [x] `release:preflight`가 production PWA를 임시 디렉터리에 빌드하고 정책 검사를 실행하도록 구현한다.
- [x] `prepareRelease()`가 후보 디렉터리를 만들기 전에 같은 preflight를 호출하도록 연결한다.
- [x] `node --test tools/release-pwa-policy.test.mjs tools/release-version.test.mjs`가 통과하는지 확인한다.

### Task 3: 실제 release AAB hardening 검증

**Files:**
- Modify: `tools/release-candidate.mjs`
- Modify: `tools/android-release.test.mjs`
- Modify: `apps/pwa/capacitor-config.test.js`

**Interfaces:**
- Consumes: bundletool이 추출한 release AAB manifest XML과 signing metadata
- Produces: manifest 정책을 통과한 `inspectAndroidBundle()` 결과

- [x] AAB fixture manifest에 `android:debuggable="true"`, `android:usesCleartextTraffic="true"`,
  `android:allowBackup="true"`를 각각 넣었을 때 거절하는 테스트를 작성한다.
- [x] release manifest가 `debuggable` 미지정 또는 `false`, `usesCleartextTraffic=false`,
  `allowBackup=false`일 때 통과하는 테스트를 작성한다.
- [x] 테스트를 실행해 현재 산출물 검사가 이 조건을 차단하지 못해 실패하는 것을 확인한다.
- [x] `inspectAndroidBundle()`이 실제 AAB manifest에서 위 세 조건과 package
  `com.makecdev.coderemotemanager`를 검증하도록 구현한다.
- [x] unsigned 후보와 최종 signed 제출본의 상태를 manifest에 명시하고 debug certificate를
  release 서명으로 인정하지 않도록 기존 certificate 검증과 연결한다.
- [x] `node --test tools/android-release.test.mjs apps/pwa/capacitor-config.test.js`가 통과하는지 확인한다.

### Task 4: 패키지 경계와 심사용 데모 확인

**Files:**
- Modify: `tools/release-pwa-policy.test.mjs`
- Modify: `apps/pwa/src/features/review-demo/review-demo.test.js`
- Modify: `tools/release-version.test.mjs`

**Interfaces:**
- Consumes: production PWA와 release candidate manifest
- Produces: 개발 파일 없는 패키지와 의도적으로 유지된 합성 review demo

- [ ] production PWA에 `.env`, `config.local.json`, 테스트 fixture, Vite client와 source map이 없음을 검사한다.
- [ ] review demo 직렬화 결과에 절대 경로·자격 증명·실제 프로젝트 데이터가 없고
  `fetch`, `EventSource`, 공용 `request()`를 호출하지 않는 기존 테스트를 강화한다.
- [ ] review demo 진입점은 native 연결 및 인증 화면에만 의도적으로 남아 있음을 확인한다.
- [ ] source·Windows·Android 후보가 동일한 embedded PWA hash를 가진다는 기존 manifest 검사를 유지한다.
- [ ] 관련 focused test를 실행해 모두 통과하는지 확인한다.

### Task 5: 무료 1.0.0 후보 생성과 저장소 검증

**Files:**
- Modify: `docs/PRE_RELEASE_CHECKLIST.md`
- Generated and ignored: `dist/release-candidate/**`

**Interfaces:**
- Consumes: `release:preflight`
- Produces: source·Windows·Android `1.0.0` 후보와 `release-manifest.json`

- [ ] `git status --short`가 clean인지 확인한다.
- [ ] `npm.cmd run release:preflight`를 실행한다.
- [ ] `npm.cmd test`를 실행하고 실패 0건을 확인한다.
- [ ] `npm.cmd --workspace apps/pwa exec vite build`를 실행한다.
- [ ] `npm.cmd audit`에서 취약점 0건을 확인한다.
- [ ] `git diff --check`를 실행한다.
- [ ] `npm.cmd run release:prepare`로 후보를 생성한다.
- [ ] `npm.cmd run release:verify`로 후보 manifest와 모든 artifact hash를 다시 검증한다.
- [ ] 후보 또는 공개 출력에 로컬 경로·자격 증명·서명 비밀이 없는지 확인한다.
- [ ] 후보 생성 결과만 `docs/PRE_RELEASE_CHECKLIST.md` 완료 요약에 기록한다.

### Task 6: 서명 후 제출 직전 점검

**Files:**
- Modify: `docs/PRE_RELEASE_CHECKLIST.md`
- Verify: `docs/STORE_LISTING.md`
- Verify: `distribution/PRIVACY.txt`
- Verify: `distribution/TERMS.txt`
- Verify: `distribution/THIRD_PARTY_NOTICES.txt`

**Interfaces:**
- Consumes: 별도 승인으로 서명된 Android AAB와 Windows `1.0.0` 후보
- Produces: Google Play 제출 여부만 남은 검증 완료 상태

- [ ] 운영자 승인 후 release keystore로 AAB를 서명하고 certificate SHA-256을 manifest와 대조한다.
- [ ] 운영자 승인 후 새 Android 실기기에 설치해 versionName `1.0.0`, versionCode `2`,
  page size와 앱 실행을 확인한다.
- [ ] QR 연결, 코드 연결, 인증 실패, Chat, 승인, Changes, 알림, 이미지 첨부, 음성 입력을 수동 검증한다.
- [ ] `Try review demo`의 합성 Chat·승인·Changes 흐름을 390×844에서 한국어와 영어로 확인한다.
- [ ] Windows clean-user 설치·시작·업데이트·제거와 사용자 데이터 보존을 확인한다.
- [ ] Play Console의 무료·인앱 결제 없음, App Access, Data Safety, 콘텐츠 등급, 국가,
  연락처와 공개 정책 URL을 최종 바이너리 동작과 대조한다.
- [ ] `coderemote@makecdev.com` routing과 실제 수신 시험 결과 또는 운영자가 승인한 보류 상태를 기록한다.
- [ ] Google Play 제출은 실행하지 않고 별도 최종 승인을 요청한다.

## 임시 노트 삭제 조건

다음 조건을 모두 만족한 커밋에서 이 파일을 삭제한다.

- Task 1~6의 모든 체크박스가 완료됐다.
- 지속 보존할 결과가 `docs/PRE_RELEASE_CHECKLIST.md` 완료 요약에 짧게 반영됐다.
- `현재 패치`가 Google Play 제출 승인 또는 그 이후의 다음 작업으로 이동했다.
- `docs/PRE_RELEASE_CHECKLIST.md`에서 이 파일 링크를 제거했다.
- 같은 커밋에 `docs/TEMP_PRE_RELEASE_HARDENING.md` 삭제를 포함했다.

일부 항목이 보류되거나 실패했다면 이 파일을 삭제하지 않는다. 이 파일에는 세션 로그, 자격 증명,
로컬 절대 경로 또는 서명 비밀을 기록하지 않는다.
