e49df07c0f
- One running game per player: server rejects a 2nd matchmake while in a live room (re-syncs the existing game); client guards Home vs-computer + Lobby random/create — resumes the running match + notifies instead of starting another (game-store hasActiveMatch()). - Background music is now selectable: santoor (سنتی, calm Persian loop) and playful (bouncy UNO-like) — sound.ts TRACKS + setMusicTrack (persisted), sound-store musicTrack, picker in Profile → Audio. i18n added. - Production config for bargevasat.ir (prepare-only; no live deploy): appsettings.Production.example (CORS + ZarinPal + IAB to the domain), docker-compose.caddy.yml + Caddyfile (auto-HTTPS reverse proxy bargevasat.ir→web, api.bargevasat.ir→server), ENV_FILE PRODUCTION block, PRODUCTION.md go-live + Cafe Bazaar publish/IAB checklist. Fixed IAB package name to match Capacitor appId (com.bargevasat.app). Verified: tsc + next build + dotnet build all pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
3.4 KiB
Markdown
58 lines
3.4 KiB
Markdown
# 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.
|