# Production go-live — bargevasat.ir + Cafe Bazaar Companion to `HANDOFF.md` / `DEPLOY.md`. Domain: **bargevasat.ir** (web) + **api.bargevasat.ir** (.NET SignalR API). Android via **Cafe Bazaar**. ## 1. DNS + firewall (you do this) - A-records → your server IP: `bargevasat.ir`, `www.bargevasat.ir`, `api.bargevasat.ir`. - Open ports **80** + **443** (`ufw allow 80 && ufw allow 443`). ## 2. Production env (Gitea `ENV_FILE` secret) Use the **PRODUCTION block** in `deploy/ENV_FILE.example`: - `NEXT_PUBLIC_SERVER_URL=https://api.bargevasat.ir` (baked at web build → needs a CI rebuild to change) - `CORS_ORIGINS=https://bargevasat.ir,https://www.bargevasat.ir` - `JWT_KEY` = `openssl rand -hex 32`, strong `POSTGRES_PASSWORD` - ZarinPal **live**: `ZARINPAL_SANDBOX=false`, live merchant id, callback `https://api.bargevasat.ir/api/coins/pay/callback`, return `https://bargevasat.ir` - ZarinPal panel: register the callback domain. ## 3. Deploy with HTTPS (Caddy) The deploy job (or you, on the server) runs the stack **with the Caddy overlay**: ```bash docker compose -f docker-compose.yml -f docker-compose.caddy.yml up -d ``` Caddy auto-provisions Let's Encrypt certs and proxies `bargevasat.ir → web`, `api.bargevasat.ir → server`. SignalR WebSockets pass through transparently. (To wire this into CI, add `-f docker-compose.caddy.yml` to the deploy job's compose commands once DNS resolves.) ## 4. Database (Supabase or the bundled Postgres) - Bundled `db` service works for launch. For Supabase: set `Database__Provider=postgres` + the Supabase `ConnectionStrings__Default`, and **generate EF migrations** first (`HANDOFF.md` §5.1) so the server runs `Migrate()` instead of `EnsureCreated()`. - **Back up before every deploy** (the deploy job already `pg_dump`s). ## 5. Cafe Bazaar (Android) publish 1. **Build a signed release APK/AAB** — `NEXT_PUBLIC_STORE=bazaar`, `NEXT_PUBLIC_APP_PACKAGE=com.bargevasat.app`, `NEXT_PUBLIC_USE_SERVER=1`, `NEXT_PUBLIC_SERVER_URL=https://api.bargevasat.ir`, then `npm run cap:sync` + build in Android Studio / gradle (see `ANDROID.md`). App id **com.bargevasat.app**. 2. Upload to **pardakht.cafebazaar.ir**, fill the listing (icon, screenshots, fa description), submit for review. 3. **In-app billing (after approval):** in the Bazaar dev panel create the coin SKUs (`p1`–`p4`, matching `ProfileService.Packs`), create the **Pardakht API** OAuth client, do the one-time consent to get a **refresh token**, and put `IAB_BAZAAR_CLIENT_ID/SECRET/REFRESH_TOKEN` (+ `IAB_PACKAGE_NAME=com.bargevasat.app`) into `ENV_FILE`; set `IAB_ALLOW_UNVERIFIED=false`. The web client deep-links `bazaar://in_app?...` and the server verifies the returned `purchaseToken` before crediting (see `HANDOFF.md` §5.3 / `src/lib/storeBilling.ts`). 4. Set `Zarinpal__Sandbox=false` only for the **web/PWA** payment path; the **store build uses IAB, not ZarinPal** (store policy). ## 6. Pre-launch hardening checklist - [ ] `JWT_KEY` is a real 32+ char secret (compose `${JWT_KEY:?}` fails if unset). - [ ] `IAB_ALLOW_UNVERIFIED=false`, `ZARINPAL_SANDBOX=false`. - [ ] CORS = the real domains only (no localhost). - [ ] DB backups confirmed (`/opt/hokm-backups`), volumes named (no orphan data — see DEPLOY.md incident rules). - [ ] CI green: tsc + next build + dotnet build + Hokm.Sim. - [ ] Smoke test on https://bargevasat.ir: OTP login, vs-AI game, ranked match, buy-coins redirect, friends/chat.