Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Successful in 50s
ci / 모바일 린트·타입·Jest (push) Successful in 38s
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 21s
ci / .NET API 서버 테스트 (push) Successful in 11s
deploy-site / deploy (push) Successful in 33s
ci / 워크스페이스 빌드 검증 (push) Has been cancelled
102 lines
6.8 KiB
Markdown
102 lines
6.8 KiB
Markdown
# 09 — Backend: Supabase + Cloudflare Map
|
|
|
|
> Surfaces: `server/supabase` (Postgres + Deno Edge Functions), `server/cloudflare-worker` (edge gateway)
|
|
> Role: canonical product data, auth, RLS, storage, AI proxies, billing, notifications
|
|
|
|
---
|
|
|
|
## 1. Supabase project (`server/supabase/`)
|
|
|
|
- `config.toml` — project_id `d3ro-voice`; local ports API 55321 / DB 55322 / Studio 55323 / Inbucket 55324; DB major v17; storage 50 MiB; auth `site_url` localhost:5173, redirects include `https://d3ro.chanpaca.net` and `d3ro-voice://auth-callback`; external providers Google/GitHub/Apple; per-function `verify_jwt` settings; analytics off.
|
|
- `seed.sql`, `migrations/` (63), `functions/` (~27), `functions/_shared/`, `tests/`, `deno.json`.
|
|
|
|
> Note: root `supabase/` contains only empty scaffolding (`.branches/`, `snippets/`). The real project lives under `server/supabase/`.
|
|
|
|
### 1.1 Migrations (62) — thematic groups
|
|
|
|
| Theme | Examples |
|
|
|---|---|
|
|
| Core schema + RLS + auth triggers | initial tables, profiles, triggers |
|
|
| Storage buckets | audio, meeting documents, exports |
|
|
| Teams | team invites, membership, roles, `team_activities` feed (`20260913000033`) |
|
|
| Cross-device sync | `20260927000034`: `sync_tombstones` (AFTER DELETE triggers on 8 synced tables, owner-read RLS, realtime, `prune_sync_tombstones_v1`), `history.revision` bump on content change, `meeting_memos.updated_at`, `(user_id, updated_at, id)` cursor indexes, client-keyed `sync_upsert/delete_user_template_v1`, realtime for `devices`/`memo_tags`/`custom_instructions`/`user_templates`, and `export_account_portability` projected back onto v1 archive keys |
|
|
| Knowledge / RAG | `knowledge_documents`, `knowledge_chunks`, pgvector |
|
|
| Notifications / push | push tokens, durable outbox |
|
|
| Billing | Payple, subscriptions, payment provider events/operations (`'stripe'` provider values kept only for historical rows) |
|
|
| Admin | admin roles, audit log, atomic admin RPCs |
|
|
| Mobile platform | mobile platform/monetization/runtime integrity |
|
|
| Commands | atomic command reorder |
|
|
| Devices | device registration + revocation |
|
|
| Content reporting | report reasons, generation receipts |
|
|
| Meetings | meeting documents |
|
|
| STT quota | atomic quota reservations (00026) |
|
|
| Ads | ad reward receipt replay protection (00028) |
|
|
|
|
Migration numbering referenced in SSOT goes up to `00028`; CI verifies `migration-up` + shadow replay.
|
|
|
|
### 1.2 Edge Functions (~27)
|
|
|
|
| Function | Purpose |
|
|
|---|---|
|
|
| `stt-proxy` | User STT gateway: auth, atomic quota reservation/refund, provider fallback, fail-closed |
|
|
| `llm-proxy` | LLM gateway (Claude/OpenAI) |
|
|
| `realtime-token` | OpenAI Realtime ephemeral token (tier-gated, session quota) |
|
|
| `generate-meeting-document` | AI document generation (minutes/report/idea-note/mindmap) |
|
|
| `embed-chunks` / `search-knowledge` | RAG embeddings + semantic search |
|
|
| `content-report` | AI content reporting |
|
|
| `team-invite` / `team-accept` | Team invitations |
|
|
| `send-push` | Push delivery |
|
|
| `account-delete` | Account deletion cascade + provider unlink |
|
|
| `admin-users` / `admin-subscriptions` / `admin-payments` / `admin-audit-log` | Admin operations |
|
|
| `billing-catalog` | Server pricing catalog. Prices/quotas read `PLAN_PRICE_KRW`/`PLAN_QUOTA` from `functions/_shared/core-contract.generated.ts`, generated from `packages/core/src/plan-catalog.ts` by `scripts/ci/sync-core-contract.mjs` (`npm run contract:check` fails on drift; added 2026-09-26, Wave 3, 88f24d8) |
|
|
| `payple-checkout` / `payple-manage` / `payple-renew` / `payple-webhook` | Payple billing (Korea) |
|
|
| `iap-verify` | Google Play / App Store purchase verification |
|
|
| `admob-ssv` | AdMob server-side verification + reward ledger |
|
|
| `google-play-rtdn` | Play Real-time Developer Notifications |
|
|
|
|
Shared contracts in `functions/_shared/`: admin, auth, audit, cors, quota, payple, push, llm, stt, team, generation-receipt, google-play, pubsub, generative-ai-safety (+ `*.test.ts`).
|
|
|
|
### 1.3 Tests (`server/supabase/tests/`)
|
|
|
|
Integration/E2E: content-report red e2e, content-reporting (ps1/sql), mobile platform/recording/reward-race, payment provider, mobile release preflight, public mobile runtime, push claim/outbox, team push security, STT quota.
|
|
|
|
---
|
|
|
|
## 2. Cloudflare worker (`server/cloudflare-worker/`)
|
|
|
|
- `wrangler.toml` — worker `d3ro-voice-api`, compat 2024-04-01, `BACKEND_ORIGIN=http://192.168.0.39:5050`, optional custom domain route (commented).
|
|
- `src/index.ts` — CORS preflight, `/worker-health`, forwards to backend origin with `X-Forwarded-*` / `X-D3RO-Edge-Proxy` headers.
|
|
|
|
Cloudflare Tunnel `kd-nas` maps public hostnames to NAS services.
|
|
|
|
---
|
|
|
|
## 3. Data model (product tables, high level)
|
|
|
|
Canonical product data lives in Supabase Postgres with RLS:
|
|
|
|
- **Identity:** `auth.users` + `profiles`, roles/claims, identity links.
|
|
- **Content:** `history`, `meetings`, `meeting_memos`, `meeting_documents`, `memos`, `dictionary`, `commands`/instructions, `templates`.
|
|
- **Knowledge:** `knowledge_documents`, `knowledge_chunks` (pgvector).
|
|
- **Teams:** teams, members, invites, activity feed (`team_activities`, RPC-only writes, realtime-enabled).
|
|
- **Delivery:** `devices` (mobile + desktop `windows`/`macos`), `push_tokens`, push outbox.
|
|
- **Sync:** `sync_tombstones` — deletion log the desktop mirror (and any offline client) reads by cursor.
|
|
- **Monetization:** `subscriptions`, `payment_provider_events/operations`, `ad_reward_claims`, IAP receipts, generation receipts.
|
|
- **Ops:** `audit_log` + admin operation records.
|
|
- **Portability:** `portable_exports` (+ storage).
|
|
|
|
Shared TS types for these live in `packages/api-client` (SSOT).
|
|
|
|
---
|
|
|
|
## 4. Backend status summary
|
|
|
|
- Auth (email + Google/GitHub/Apple), RLS, storage, realtime: **implemented**; production Auth + Google provider entry verified GREEN; GitHub/Apple provider secrets and mobile consent callback pending (external).
|
|
- STT/LLM proxies: **implemented** and fail-closed (no synthetic transcripts); atomic quota reservations verified with 20-way concurrency.
|
|
- Billing (Payple + IAP verify + webhooks/RTDN; Stripe removed 2026-09-26): **implemented**; live provider end-to-end and Payple webhook signature verification pending.
|
|
- Ads (AdMob SSV, rewarded ledger, replay protection): **implemented** (Edge v13 ACTIVE); production AdMob serving blocked externally (review/serving limits/store link/payment profile).
|
|
- Push: Supabase owns tokens/devices/outbox/retries. Transports implemented for **FCM, Web Push (VAPID + RFC 8291), and APNs (.p8 token)**; the Cloudflare Worker cron drains the outbox every minute. Android still requires FCM at the device. Details: `docs/deployment/push-transport-without-firebase.md`.
|
|
- Content safety: generation receipts + `content-report` **implemented**.
|
|
- Data portability (`account-delete`, export/restore): **implemented**.
|
|
|
|
External gates are enumerated in `docs/v3/MOBILE_APP_COMPLETION_SSOT.md` §0/§6 and mirrored in `11-gap-backlog.md` (`EXT-*`, `BE-*`).
|