- docs/REFACTOR_WAVE3_REPORT.md and the Wave 3 policy: canonical map, production changes, verification and remaining external steps. - Gap backlog: GAP-BILL-01 resolved; new GAP-BILL-02 (Payple renewal never ran, Payple client key never set), GAP-WEB-01 (tunnel host for /app), GAP-OPS-01 (NAS compose/.env drift), GAP-CI-01, GAP-I18N-02, GAP-TEAM-02. - design.md: hero loop decision (numbers taken from the app capsule), pricing mismatch closed; feature catalog SHELL-11 updated. - docs/map, release guide and mobile release docs no longer describe the deleted wwwroot, binaries, Dockerfile.admin, NAS site copy or .github CI. - docker-compose.nas.yml gains the d3ro-whisper service that only existed in the NAS copy, so the repository file is the complete definition. - refactor-wave skill: Wave 3 index and lessons P10-P12.
101 lines
6.2 KiB
Markdown
101 lines
6.2 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`) |
|
|
| Knowledge / RAG | `knowledge_documents`, `knowledge_chunks`, pgvector |
|
|
| Notifications / push | push tokens, durable outbox |
|
|
| Billing | Payple, Stripe, subscriptions, payment provider events/operations |
|
|
| 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) |
|
|
| `stripe-checkout` / `stripe-portal` / `stripe-webhook` | Stripe billing |
|
|
| `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 (Stripe + Payple + IAP verify + webhooks/RTDN): **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-*`).
|