Files
flatrender/backend/db
soroush.asadi ec51e87d2d feat(payment): standalone ZarinPal broker on pay.flatrender.ir
A generic multi-client payment gateway so FlatRender, meezi.ir and
bargevasat.ir can all pay through ZarinPal's single verified callback
domain (pay.flatrender.ir).

New Go service services/payment (clones the notification skeleton +
vendored deps):
- migration 31_payment_broker.sql — `payment` schema: client_apps,
  transactions, webhook_deliveries.
- ZarinPal v4 client ported from the proven identity PaymentService
  (request.json -> StartPay -> verify.json; codes 100/101).
- client API: POST /v1/pay/request + /v1/pay/inquiry, authed by
  X-Api-Key + HMAC body signature; GET /callback/zarinpal (the single
  verified endpoint) verifies, then 302s the user back to the site's
  return_url (signed) and fires a signed, retried webhook.
- per-client ZarinPal merchant override (default = shared merchant);
  amount stored canonically in Rial, unit to ZarinPal env-configurable.
- admin API /v1/admin/* (FlatRender admin JWT): client-app CRUD +
  key issue/rotate + transactions list.

Deploy wiring: payment-svc in docker-compose.v2.yml (host port 1607),
pay.flatrender.ir server block in mirror-nginx conf, ENV_FILE +
README updates (cert SAN + manual migration note).

Admin UI: src/components/admin/PaymentsAdmin.tsx (client apps with
one-time key reveal + rotate, transactions table) + /admin/payments
page + nav link + fa/en strings; pay-admin proxy route to payment-svc.

Docs/SDK: deploy/PAYMENTS.md (integration contract) + deploy/sdk/flatpay.js
(zero-dep Node client + webhook verifier) for meezi/any site.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 23:59:54 +03:30
..

FlatRender V2 — Database Schemas

PostgreSQL 15+. Single database, one schema per microservice.

Run order

Apply migrations in numerical order:

psql -d flatrender -f migrations/00_setup.sql
psql -d flatrender -f migrations/01_identity_tenants.sql
psql -d flatrender -f migrations/02_identity_users.sql
psql -d flatrender -f migrations/03_identity_billing.sql
psql -d flatrender -f migrations/04_identity_gamification.sql
psql -d flatrender -f migrations/05_content_taxonomy.sql
psql -d flatrender -f migrations/06_content_projects.sql
psql -d flatrender -f migrations/07_content_scenes.sql
psql -d flatrender -f migrations/08_content_characters_presets.sql
psql -d flatrender -f migrations/09_content_cms.sql
psql -d flatrender -f migrations/10_studio_saved_projects.sql
psql -d flatrender -f migrations/11_render_nodes.sql
psql -d flatrender -f migrations/12_render_jobs.sql
psql -d flatrender -f migrations/13_file_manager.sql
psql -d flatrender -f migrations/14_notification.sql

Schemas

Schema Owner Service Purpose
identity Identity Service (.NET) tenants, users, auth, plans, payments, gamification
content Content Service (.NET) templates, scenes, presets, blogs, CMS
studio Studio Service (.NET) user's saved projects + audio (music/voiceover/sfx)
render Render Orchestrator (Go) jobs, nodes, frame jobs, snapshots, exports
file_mgr File Service (Go) user files, folders, quotas, cleanup
notification Notification Service (Go) in-app, push, email, SMS, telegram

Cross-schema design

Schemas are loosely coupled. Where it matters for integrity (within a service), FKs are used. Across services, FKs are deliberately omitted so services can evolve independently — referential integrity is enforced via service code and events.

Hard FKs across schemas (intentional)

  • identity.earned_gifts.notification_idnotification.notifications.id

Everything else uses soft references (column documented but no FK).

Multi-tenancy

identity.tenants is the root of multi-tenancy. The default FlatRender tenant has UUID 00000000-0000-0000-0000-000000000001.

Every user, project, render job, file, and notification carries a tenant_id. Resellers (B2B API customers) are tenants. White-label branding, API keys, webhooks, and usage metering all hang off identity.tenants.*.

New features (vs V1)

  • Multi-tenancy / Reseller API: identity.tenants, tenant_branding, tenant_api_keys, tenant_webhooks, tenant_usage_daily
  • Voiceover support: studio.saved_projects.voiceover_*, render.render_jobs.has_voiceover
  • Per-track volume: music_volume, sfx_volume, voiceover_volume
  • Scene snapshots: render.snapshots with cache key
  • AE crash tracking: render.node_crashes + auto-recovery
  • Frame repair jobs: render.frame_repair_jobs
  • AEP local cache on nodes: render.node_template_cache (LRU)
  • SVG color previews: content.template_svg_previews (drop image → traced SVG)
  • PWA push subscriptions: identity.push_subscriptions
  • MFA: identity.mfa_factors
  • Multipart uploads: file_mgr.upload_sessions
  • Cleanup scheduler: file_mgr.cleanup_schedules
  • Per-user / per-channel notification preferences: notification.notification_preferences

Partitioning

Time-series tables are partitioned monthly (initial partition for 2026-01 created; ops creates new ones via cron):

  • identity.tenant_api_request_logs
  • render.node_health_logs

Service user grants

Each microservice connects with its own DB role limited to its schema. See top of 00_setup.sql for the recipe.