Commit Graph

8 Commits

Author SHA1 Message Date
soroush.asadi 4cc1c3a423 feat(payment): FlatRender Pay (ZarinPal broker) checkout + webhook
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m3s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 37s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m10s
CI/CD / CI · Admin Web (tsc) (push) Successful in 37s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 53s
CI/CD / Deploy · all services (push) Successful in 1m41s
Adds a signed broker integration for online plan purchases:
- FlatPayService: POST /v1/pay/request with X-Api-Key + X-Signature =
  hex(HMAC-SHA256(secret, raw JSON bytes)); the exact serialized bytes are both
  signed and sent. VerifyWebhook does a fixed-time compare of the digest, plus an
  in-memory first-seen idempotency set.
- POST /api/payment/request (auth, ManageBilling): parses a "Tier:Months" product
  (e.g. "Pro:12"), prices it via the plan catalog, creates a Pending SubscriptionPayment
  (provider=FlatPay) as the order, and returns the broker payment URL. The order id is
  the client_ref / metadata.payment_id.
- POST /api/payment/webhook (anonymous; HMAC is the auth — 401 on bad signature):
  on status=Paid + first-seen id, grants the order via the shared plan-activation
  path (extracted ActivatePaymentAsync, reused by all providers). Always 200 after a
  valid signature so the broker won't retry an accepted job.
- Config FlatPay__{ApiKey,Secret,BaseUrl,ReturnUrl} (env-supplied; secrets stay out
  of git), compose + .env.example wiring. PaymentProvider.FlatPay appended (int, no
  migration).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 04:20:02 +03:30
soroush.asadi 8ea98bdc09 fix(seo): website/koja base URL defaulted to localhost → de-indexed in GSC
CI/CD / CI · API (dotnet build + test) (push) Successful in 5m47s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 34s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m10s
CI/CD / CI · Admin Web (tsc) (push) Successful in 40s
CI/CD / CI · Website (tsc) (push) Successful in 47s
CI/CD / CI · Koja (tsc) (push) Successful in 51s
CI/CD / Deploy · all services (push) Successful in 3m53s
Production serves robots.txt Host/Sitemap, sitemap <loc>, and every page's
canonical + og:url as http://localhost:3010 — so Google rejects all URLs
("URL not allowed") and indexes nothing. Cause: NEXT_PUBLIC_SITE_URL is baked in
at BUILD time and was unset in prod, so it fell back to the localhost defaults in
the compose files + website Dockerfile.

Changes the defaults to the real domains (website → https://meezi.ir, koja →
https://koja.meezi.ir) in docker-compose.yml, docker-compose.full.yml, the
website Dockerfile ARG, and .env.example.

Build-time var → the website image MUST be rebuilt + redeployed (CI does this on
push), then purge the WCDN cache and resubmit the sitemap in Search Console.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 18:58:38 +03:30
soroush.asadi 255695e8ae fix(deploy): auto-migrate on boot + seed admin credentials from env
CI/CD / CI · API (dotnet build + test) (push) Successful in 47s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 43s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 46s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Successful in 3m36s
- docker-compose.admin.yml: RUN_MIGRATIONS was hardcoded false → now
  uses ${RUN_MIGRATIONS:-true} so migrations run automatically on deploy
- Both compose files: expose Seed__SystemAdminPhone/Username/Password
  env vars so the seeder sets admin credentials without manual SQL
- .env.example: document SEED_ADMIN_* variables

On next deploy: migrations run, Username='admin' is patched on the
existing admin, and password is hashed from SEED_ADMIN_PASSWORD.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 20:10:56 +03:30
soroush.asadi 345ae0a4b5 first commit
CI/CD / CI · Admin API (dotnet build) (push) Successful in 41s
CI/CD / CI · Admin Web (tsc) (push) Failing after 5s
CI/CD / CI · Website (tsc) (push) Failing after 4s
CI/CD / CI · Koja (tsc) (push) Failing after 5s
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m13s
CI/CD / CI · Dashboard (tsc) (push) Failing after 2m32s
CI/CD / Deploy · all services (push) Has been skipped
2026-05-31 11:06:24 +03:30
soroush.asadi 289c808257 Rename public discovery app from "finder" to "koja"
Rebrand the public café-discovery app: directories web/finder→web/koja and
docker/finder→docker/koja, plus all service wiring (docker-compose, Caddy
subdomain koja.meezi.ir, env vars KOJA_PORT / NEXT_PUBLIC_KOJA_URL, CI
workflows) and the app's display name (Koja / کجا).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 17:02:22 +03:30
soroush.asadi 16cff8730b feat : kavenegar otp added 2026-05-29 10:18:47 +03:30
soroush.asadi 88a9f96108 feat(infra): parameterize secrets, add Caddy reverse proxy for domain
All hardcoded passwords/keys replaced with env vars so .env controls
everything in both dev and production:
  - DB_PASSWORD, DB_CONNECTION_STRING, JWT_KEY
  - CORS_ORIGIN_*, ASPNETCORE_ENVIRONMENT
  - All ZarinPal/Kavenegar/Snappfood secrets

New files for tomorrow's domain setup:
  - Caddyfile        → routes all subdomains with auto TLS
  - docker-compose.caddy.yml → adds Caddy service to the stack

.env.example now has clear TODAY (IP) vs TOMORROW (domain) sections.
Fixed hardcoded ZarinPal MerchantId in docker-compose.full.yml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 18:54:55 +03:30
soroush.asadi 45cd028d1c chore: initial project structure and root configuration
Adds root-level config files: solution (.slnx), NuGet, global.json,
Docker Compose files for all services (API, dashboard, website, finder,
admin), environment example, and developer documentation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 21:33:10 +03:30