English {#english}
Status: Implemented — CP/Zuplo/www no longer expose phone SMS OTP; runbooks and platform hub copy updated accordingly.
Goal: Remove all phone-number SMS OTP verification (historically Twilio, currently Bird) from the manual trial approval funnel. Email-based verification only for the paths that still need proof of control (e.g. work-email OTP via Resend where already implemented).
Non-goals (this phase): Removing POST /v1/trial/email/check, Abstract/heuristics, Resend email OTP for manual approval, or admin handoff — unless a separate decision retires them.
Product rule (before removal): Flows that gated submit-details on is_phone_verified were redesigned to email verification (is_email_verified where applicable) and E.164 contact mobile without SMS.
Canonical touchpoints (pre-removal snapshot)
| Area | What this plan targeted for removal or change |
|---|---|
| prego-control-plane | POST /v1/trial/manual-approval/phone/send-otp, POST /v1/trial/manual-approval/phone/verify-otp; src/trial-access/phone-otp.ts (SMS/Bird + phone OTP rate limits — split or delete); handleManualApprovalSubmit / draft loaders that gate on is_phone_verified; Worker Env Bird + phone-specific OTP_PEPPER usage for SMS; src/index.ts route registrations. |
| prego-control-plane D1 | Columns from 0027 (otp_hash, otp_expires_at, phone_e164_pending, is_phone_verified, …): either leave nullable for history or add a later migration to drop unused columns — decision in implementation. |
| prego-control-plane admin | Operator UI that shows phone verified / phone_e164_pending (admin/src/features/cp-trial-access, cp-types) — hide or remove columns when SMS is gone. |
| prego-zuplo | OpenAPI /api/trial/manual-approval/phone/*; modules/trial-access-handlers.ts proxies; after OAS change: pnpm run sync-oas then pnpm run verify. |
Prego apps/www | ManualApprovalVerifyForm, lib/trial-gateway.ts (send-otp / verify-otp), manual-approval-verify-schema.ts phone fields — remove SMS steps; adjust copy and steps so only email verification remains where required. |
Implementation outcome: Public phone/* routes removed from CP and Zuplo; BIRD_* no longer used for manual trial SMS; CP admin trial-access UI no longer lists phone-verified / phone-pending; www manual-approval verify flow is work-email OTP plus contact mobile (E.164) without SMS; shared phone-otp.ts remains for email OTP hashing / rate-limit helpers where applicable. D1 0027 columns may remain for history until a separate migration drops them.
Contract order (when implementing): OpenAPI in prego-zuplo first → routes → Worker / www (see How to add an API — same order applies to removal of public paths).
Secrets / env: After removal, Bird (BIRD_*) and any phone-only pepper usage can be deleted from Worker secrets; confirm nothing else imports phone-otp.ts rate limits for email (email OTP may still use trial_otp_ip_rate with email_otp_sent — verify before deleting shared helpers).
Risks: Users mid-flight on /trial/manual-approval/verify with partial phone flow; operator reports that relied on phone-verified column. Mitigation: deploy www + CP together; optional short period of 410 Gone on phone routes with JSON message.
Related: Bird SMS plan (superseded by this removal) · Trial email handoff · prego-control-plane README (trial table).
한국어 {#korean}
1. 목적
- 휴대폰 SMS OTP(과거 Twilio, 현재 Bird) 기능을 완전히 제거한다.
- 수동 승인(Manual approval) 경로에서는 이메일 인증만 유지한다(예: 업무 이메일 OTP — Resend, 기존 구현 기준).
- 코드 작성은 이 문서 범위에 포함하지 않는다.
2. 비목표
- 일반 트라이얼 이메일 분류
POST /v1/trial/email/check전체 제거(별도 결정 없으면 유지). - Resend 기반 이메일 OTP·드래프트( D1 0028 ) 제거 — 본 기획의 “이메일만”과 충돌하지 않도록 SMS만 삭제 대상으로 한정.
3. 삭제·변경 대상 (구현 시 참고)
-
공개 HTTP
- Control Plane:
.../phone/send-otp,.../phone/verify-otp제거 또는 즉시 410/명시적 JSON 응답(전환기간 정책에 따라 선택). - Zuplo: 동일 경로
/api/trial/manual-approval/phone/*및 핸들러 프록시 제거. - OpenAPI 조각 갱신 후 sync-oas / verify.
- Control Plane:
-
비즈니스 규칙
submit-details등에서is_phone_verified필수 조건을 제거하고, 이메일 검증(is_email_verified) 등 이메일 측 요건만 남길지 제품이 확정해야 한다.- 휴대폰 번호는 연락처 입력만(형식 검증)으로 둘지, 필드 자체를 선택으로 둘지 별도 결정.
-
프론트(www)
- SMS 발송·인증 UI·
trial-gateway의 phone OTP 호출·스키마의phoneE164검증(OTP용) 제거 또는 “연락용”으로 축소.
- SMS 발송·인증 UI·
-
운영자 UI(CP admin)
- trial-access 목록/상세의 phone verified 표시·
phone_e164_pending노출 정리.
- trial-access 목록/상세의 phone verified 표시·
-
시크릿
BIRD_*, SMS용OTP_PEPPER분리 여부 확인 후 미사용 시 제거. (이메일 OTP가 동일 pepper를 쓰는지 코드 확인 후 삭제.)
-
데이터베이스
- 0027에서 추가된 컬럼: 보관만 할지 마이그레이션으로 DROP 할지 운영·감사 요구에 따라 선택.
4. 권장 롤아웃 순서
- 제품 문구·스텝 수(이메일만) 확정.
- OpenAPI(Zuplo) → CP → www → admin 순으로 반영하거나, 동일 배포 윈도우에서 www+CP 동시 배포로 깨진 플로우 방지.
- 배포 후 Bird·관련 Worker 시크릿 정리.
- 문서(README, AGENTS, runbook)에서 SMS·Bird 설명 삭제.
5. 리스크
| 리스크 | 완화 |
|---|---|
| 진행 중인 사용자(폰 OTP 단계) | 배포 타이밍·짧은 서버 메시지 |
감사 로그에 phone_otp_* 이벤트 의존 | 이벤트 타입 유지/아카이브 정책 |
이메일 OTP와 공유 모듈(phone-otp.ts 레이트리밋) | 리팩터 시 이메일 경로 회귀 테스트 |
요약: SMS OTP 전 구간(CP·Zuplo·www·OAS·시크릿·UI)을 제거하고, 수동 승인은 이메일 인증만 남기는 것이 목표다. 구현 시 플랫폼 계약 순서(Zuplo OpenAPI 선행)를 따른다.