feat(V2-2): Supabase 인프라 — 스키마 + RLS + Edge Functions 스캐폴딩

server/supabase/ 신규 디렉토리:

config.toml — Supabase CLI 설정
  - 프로젝트 ID, DB 포트, auth providers (Google/GitHub/Apple),
    edge_runtime, functions.*.verify_jwt 설정

migrations/ (PostgreSQL DDL, 시간순):
  - 20260409000001_initial_schema.sql
    12개 테이블: profiles, teams, team_members, meetings,
    meeting_memos, meeting_documents, transcripts, history,
    dictionary, memo_tags, daily_usage, subscriptions
    + 인덱스 + FK CASCADE + transcripts Realtime publication
  - 20260409000002_rls_policies.sql
    개인 전용(history/dictionary): user_id = auth.uid()
    팀 공유(meetings 등): 본인 OR team_members 조회 subquery
    daily_usage: 읽기만, 쓰기는 service_role RPC
  - 20260409000003_auth_triggers.sql
    handle_new_user — auth.users INSERT → profiles+subscriptions 자동 생성
    moddatetime — 8개 테이블 updated_at 자동 갱신
    increment_daily_usage — service_role 전용 쿼터 RPC
  - 20260409000004_storage_buckets.sql
    audio/exports/avatars 3개 버킷 + 경로 기반 접근 정책
    (파일 경로가 {user_id}/...로 시작해야 쓰기 허용)

functions/ (Deno/TypeScript Edge Functions):
  - _shared/cors.ts — CORS 헤더 + preflight 핸들러
  - _shared/auth.ts — requireUser (JWT 검증 + User 반환)
  - _shared/quota.ts — 티어별 쿼터 체크 + consume + service role client
  - stt-proxy/index.ts — Google Cloud STT 래퍼 스캐폴딩
    placeholder 응답, 실제 API 호출 코드는 주석으로 포함
  - llm-proxy/index.ts — Anthropic Messages API 래퍼 스캐폴딩
    티어별 허용 모델 정책 (free=Haiku, pro=Sonnet, team=Opus)

설계 문서:
  - docs/v2/phase-V2-2.md — 상세 설계 (스키마/RLS/Edge Functions/Realtime)
  - docs/v2/phase-V2-2-setup.md — 사용자 액션 가이드 (Supabase 계정/
    OAuth 등록/CLI/배포/검증)

apps/desktop typecheck 통과 (server/는 Deno 런타임이라 별도).
실제 Supabase 프로젝트 배포는 사용자가 phase-V2-2-setup.md 따라 수행.
This commit is contained in:
yunchan8804 2026-04-08 15:21:08 +09:00
parent 3524e958ba
commit 97eb886ec3
16 changed files with 1675 additions and 8 deletions

View file

@ -6,12 +6,12 @@
## 현재 단계
**V1 (Electron) 완료** → **V2 (Monorepo) 진행 중**
- Phase V2-1 (전체) ✅ 완료
- V2-1a: Monorepo 구조 이동
- V2-1b: packages/core 추출
- V2-1c: packages/ui 추출
- V2-1d: packages/i18n 추출
- 다음: Phase V2-2 (Supabase 인프라)
- Phase V2-1 ✅ 완료 (Monorepo 전환 — a/b/c/d)
- Phase V2-2 🟡 로컬 작업 완료, 사용자 액션 대기
- SQL 마이그레이션 4개 파일 + Edge Functions 2개 스캐폴딩 작성 완료
- Supabase 프로젝트 생성/OAuth 등록/배포는 사용자가 직접 수행
- 가이드: `docs/v2/phase-V2-2-setup.md`
- 다음: Phase V2-3 (Web App MVP — Next.js)
## V1 완료 페이즈
@ -138,8 +138,43 @@
- `npm run dev` ✅ 실제 실행 → DB 경로 `d3ro-voice/`로 복원, 기존 핫키(Alt keyCode=2) 로드, Ollama 자동 실행 감지 모두 정상
- `npm run dist` (electron-builder installer)은 V2-1 완료 후 별도 검증
### Phase V2-2~V2-8: 미착수
Supabase 인프라, Web App MVP, 데스크톱 동기화, Mac 빌드, Mobile App, 팀 기능, 결제/출시
### Phase V2-2: Supabase 인프라 — 로컬 작업 완료
**작성된 파일** (`server/supabase/`)
- `config.toml` — Supabase CLI 설정 (로컬 + OAuth providers)
- `migrations/20260409000001_initial_schema.sql` — 12개 테이블 (profiles, teams, team_members, meetings, meeting_memos, meeting_documents, transcripts, history, dictionary, memo_tags, daily_usage, subscriptions) + 인덱스 + FK CASCADE
- `migrations/20260409000002_rls_policies.sql` — 개인/팀 이중 RLS 패턴
- `migrations/20260409000003_auth_triggers.sql``handle_new_user` (profiles + subscriptions 자동 생성), `moddatetime` (8개 테이블 updated_at 트리거), `increment_daily_usage` (service_role 전용 쿼터 RPC)
- `migrations/20260409000004_storage_buckets.sql` — audio/exports/avatars 버킷 + 경로 기반 정책
- `functions/_shared/` — cors.ts, auth.ts (requireUser), quota.ts (티어별 쿼터)
- `functions/stt-proxy/index.ts` — Google Cloud STT 래퍼 스캐폴딩 (placeholder 응답)
- `functions/llm-proxy/index.ts` — Anthropic Messages API 래퍼 스캐폴딩 (티어별 모델 정책)
- `seed.sql` — 개발 시드 (빈 상태)
- `.gitignore` — .branches/, .temp/, .env
**설계 문서**
- `docs/v2/phase-V2-2.md` — 상세 설계 (스키마/RLS/Edge Functions/실시간/Storage)
- `docs/v2/phase-V2-2-setup.md` — 사용자 액션 가이드 (Supabase 계정/OAuth/CLI/배포)
**사용자 액션 대기 중** (로컬 외 작업)
1. Supabase 프로젝트 생성 (https://supabase.com)
2. `supabase login && supabase link --project-ref <REF>`
3. `supabase db push` (4개 마이그레이션 적용)
4. Google/GitHub OAuth 앱 등록 + Supabase Auth Providers 설정
5. Google Cloud STT 키 + Anthropic API 키 발급
6. `supabase secrets set` + `supabase functions deploy`
**설계 결정사항**
- **UUID PK**: V1은 nanoid(text), V2는 PostgreSQL `gen_random_uuid()`. V2-4 (동기화)에서 기존 SQLite 데이터는 nanoid 유지, 새 데이터는 UUID.
- **timestamptz**: V1은 epoch ms(integer), V2는 `timestamptz`. V2-4 동기화 시 타입 변환 필요.
- **멀티테넌시**: 모든 테이블에 `user_id`. 회의 관련 테이블은 `team_id` nullable 추가.
- **RLS 이중 패턴**: 개인 전용(history/dictionary)은 단순 `user_id = auth.uid()`. 팀 공유(meetings)는 본인 OR `team_members` 조회 subquery.
- **쿼터 집계**: `increment_daily_usage` RPC는 `SECURITY DEFINER` + `service_role` only. 일반 유저는 읽기만.
- **Realtime**: `transcripts` 테이블만 `supabase_realtime` publication에 추가 (회의 중 세그먼트 동기화 용).
- **Edge Functions placeholder**: 인증/쿼터 파이프라인은 완성, 실제 AI API 호출은 주석 처리된 실제 구현 코드 포함. V2-3 (Web MVP) 진행 전까지 유지.
### Phase V2-3~V2-8: 미착수
Web App MVP, 데스크톱 동기화, Mac 빌드, Mobile App, 팀 기능, 결제/출시
## 알려진 차단/이슈