feat(desktop): SaaS [6] 로컬 우선 sync + login_required UI (빅뱅 Phase 3)
Phase 3 재정의: Supabase = source of truth 방향 철회. 로컬 entry point 철학 하에 "로컬이 SoT, 클라우드는 로그인 시 mirror"로 확정. CloudSyncService._initialSync(): - _onAuthenticated 끝에 fire-and-forget 호출 - pushAll → pullAll 순차 실행 - signin: 익명 로컬 데이터를 사용자 계정으로 업로드 - restore: 다른 기기 변경 반영 - 실패 시 warn만, 수동 Sync 버튼으로 재시도 가능 types.ts: - FeatureAccess.reason: 'login_required' 추가 - UpgradePromptEvent.reason: 'login_required' 추가 LicenseService: - consumeQuota(): login_required 케이스 — promptUpgrade + D3ROError(TierRequired) - promptUpgrade(): login_required 시 requiredTier='free' (로그인만 하면 free로 바로 사용 가능) - quota_exceeded 시 현재 tier 상위로 승격 제안 UpgradePromptModal: - isLoginRequired 분기 — title/desc 교체 - Primary button: "로그인하기" → d3ro:open-settings event (tab=cloud) i18n ko/en: - license.loginRequired.title/desc/signIn 추가
This commit is contained in:
parent
46b77f1118
commit
ceadf1b6f3
7 changed files with 103 additions and 6 deletions
|
|
@ -208,6 +208,36 @@ OAuth provider도 아직 Supabase에 설정 안 된 상태. 강제 게이트는
|
|||
- `~/Library/Application Support/d3ro-voice/users/${uuid}/d3ro.db` 파일 생성 확인
|
||||
- 기존 `d3ro-voice.db`가 있는 환경에서 archive rename 동작 확인
|
||||
|
||||
### SaaS [6] 로컬 우선 sync + login_required UI (Phase 3, 2026-04-11)
|
||||
|
||||
> 빅뱅 Phase 3의 원래 설계("Supabase = source of truth")는 로컬 entry point 철학과 충돌하므로 재정의.
|
||||
> **로컬이 source of truth, 클라우드는 로그인 시 mirror + 양방향 sync.**
|
||||
|
||||
- **CloudSyncService `_initialSync(reason)`**
|
||||
- `_onAuthenticated` 끝에 fire-and-forget으로 호출
|
||||
- 로그인 직후 `pushAll()` 이후 `pullAll()` 순차 실행
|
||||
- signin → 익명 세션 로컬 데이터를 사용자 계정으로 업로드
|
||||
- restore → 다른 기기 변경사항 반영
|
||||
- 실패해도 warn만, 수동 Sync 버튼으로 재시도 가능
|
||||
- **`FeatureAccess.reason` / `UpgradePromptEvent.reason` 확장**
|
||||
- `'login_required'` 케이스 추가 (types.ts)
|
||||
- `promptUpgrade(feature, 'login_required')` — `requiredTier: 'free'`로 emit
|
||||
- **`UpgradePromptModal` login_required 케이스**
|
||||
- Title: "X은(는) 로그인이 필요합니다"
|
||||
- Desc: "클라우드 기능을 사용하려면 로그인하세요. 로컬 기능은 로그인 없이도 계속 사용할 수 있습니다."
|
||||
- Primary button: "로그인하기" → `d3ro:open-settings` custom event (tab=cloud)
|
||||
- **LicenseService.consumeQuota()** 에도 `login_required` 케이스 추가 — promptUpgrade + D3ROError(TierRequired)
|
||||
- **i18n ko/en**: `license.loginRequired.title/desc/signIn`
|
||||
- **검증**
|
||||
- desktop `tsc --noEmit` ✅
|
||||
- desktop `npm run build` ✅ (renderer 2,130kB)
|
||||
- 실증은 OAuth provider 연결 후 Phase 5에서
|
||||
|
||||
**Phase 3에서 의도적으로 뺀 것 (후속 사이클로)**
|
||||
- **auto push on write** — VoiceMode / MeetingMode session 완료 즉시 `pushOne()`. 현재는 수동 Sync 버튼 + Realtime debounced pull만. 실제 구현은 각 서비스에 hook 추가가 필요하므로 규모 큼.
|
||||
- **오프라인 WriteQueue** — 네트워크 끊긴 상태에서 write → 디스크 큐 → 복귀 시 flush. 현재는 실패 시 logger.warn만.
|
||||
- **PREMIUM_LLM 실제 호출 경로** — LocalLLMService에 cloud mode 추가해서 `llm-proxy` Edge Function 호출 + canUse(PREMIUM_LLM) gate. feature enum/policy는 Phase 4에서 준비 완료.
|
||||
|
||||
### SaaS [5] 티어 enforcement — 로컬 해방 + 클라우드 gate (Phase 4, 2026-04-11)
|
||||
|
||||
> 사용자 표현: "로컬 사용자는 풀어줘야해! 클라우드 동기화 같은 것과 고급 api가 막히는거지"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue