Files
HokmPlay/PRODUCTION.md
T
soroush.asadi e49df07c0f
CI/CD / CI - API (dotnet build + engine sim) (push) Successful in 7m47s
CI/CD / CI - Web (tsc + next build) (push) Successful in 1m9s
CI/CD / Deploy - local stack (db + server + web) (push) Failing after 1s
Prod hardening: one-game-per-player, selectable music, bargevasat.ir config
- 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>
2026-06-06 23:05:52 +03:30

58 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.