d3ro-voice/docs/map/09-supabase-backend.md
Yun Chan eedd127ea7
Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Failing after 1m13s
ci / 워크스페이스 빌드 검증 (push) Has been skipped
ci / 모바일 린트·타입·Jest (push) Failing after 1m4s
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 37s
ci / .NET API 서버 테스트 (push) Successful in 27s
deploy-site / deploy (push) Failing after 20s
refactor(billing): remove Stripe; payments are Payple (web) and Google Play (mobile)
Stripe is not used. Keeping its checkout, portal and webhook paths meant a
second payment provider, a second return-URL format and dead UI.

- Delete the stripe-checkout, stripe-portal and stripe-webhook functions and
  their config; billing-catalog serves Payple prices only, and the web parser
  rejects a catalog that still mixes in Stripe prices.
- Web: drop the Stripe checkout/portal buttons, provider toggle and return
  notices; billing shows Payple only. Past rows with provider='stripe' are
  still displayed ("Stripe (종료)") with a support contact instead of a portal.
- Desktop: delete the Stripe checkout modal, payment IPC channels, preload
  namespace and their types; "Remove ads with Pro" opens the web billing page
  via license.openBilling. Support/refund copy names Payple.
- billingUrl() loses the Stripe-only success/canceled result option; the
  Deno contract is regenerated.
- Migrations and the DB's accepted provider values are untouched (history).
- Docs and the backlog record the removal (MON-04, EXT-STRIPE-01, GAP-BILL-03).

Verified: typecheck (desktop/web/admin/api-client/mobile), contract:check,
deno check all functions, deno test 80/80, desktop 1478/1480 on the Electron
runtime (2 known environment failures), web and admin builds, release
metadata and mobile boundary self-tests, eslint on changed files.
2026-09-26 20:56:18 +09:00

6.2 KiB

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)
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, push_tokens, push outbox.
  • 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-*).