Files
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

3.4 KiB
Raw Permalink Blame History

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:

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_dumps).

5. Cafe Bazaar (Android) publish

  1. Build a signed release APK/AABNEXT_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 (p1p4, 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.