← Post-phase server audit

Runtime services — deployment topology

Generated from the canonical Markdown — do not hand-edit. Audit date 2026-07-10.

Audit date: 2026-07-10 · Derivation: every entry below is justified from the code — the DI seam that depends on it, the config key that names it, or the package/startup wiring that talks to it. Nothing is invented; "not needed" claims are backed by the absence of the package/code. Make-it-real steps live in dev/shared-working-context/reports/mocks-registry.md (row references below).

The shape in one sentence: today the API binary talks to exactly one external system — SQL Server (app DB + log DB); everything else (18 seams) is an in-process mock, so "deployment" today is one container + one database — and the table below is the roadmap of what must exist as each seam goes real.

Service inventory

#ServicePurposeDepends via (seam / config)MVP?Registry row
1SQL Server (app DB Baya)System of record — 12 schemas (usr ops geo catalog verif search booking payments payouts reviews messaging partner)EF Core; ConnectionStrings:SqlServerRequired now
2SQL Server (log DB Baya_Logs)Serilog sink in deployed envs (Warning+, auto-created log.LogEvents)ConnectionStrings:logDbRequired now (deployed)
3Reverse proxy / TLS (nginx·caddy·traefik)TLS termination, HTTP/1.1+2, forwarded headersKestrel config; JWE bearerRequired now
4Prometheus (+ Grafana)Scrapes /metrics; health forwarded to gaugesUseMetricServer + OTel exporterRecommended now
5RedisICacheService + IDistributedLock (money-path mutex)Seams:* (keys TBD; none today)Before >1 API instancerows 14, 42
6MinIO / S3 / ArvanCloudIObjectStorage — verification docs, avatars (REQ-006), invoice PDFsSeams:ObjectStorage:*Before real verificationrow 13
7Job scheduler (Hangfire/Quartz, in-app on SQL)The deferred crons: payout batch, expiry scan, no-show, Moadian pollhosted services (no interface exists)Before unattended opsrow 26
8SMS gateway (Kavenegar·Ghasedak·SMS.ir)ISmsSender — OTP delivery (login is impossible without it)Seams:Sms:* (to be added)Launch-criticalrow 12
9PSP / IPG + Shaparak (ZarinPal·Sadad·Vandar·Jibit)IPaymentProvider + IWebhookVerifier + ISettlementSplitProvider (تسهیم)encrypted payment_gateways.config_jsonReal paymentsrows 39–41
10BNPL providers (SnappPay·Digipay)IBnplProvider / IBnplProviderResolver / ICurrencyNormalizerSeams:Bnpl:*, Seams:Currency:*, gateway configOptional at launchrows 46–47
11Bank-transfer rail (Jibit·Vandar·Sadad payout API → PAYA/SATNA)IBankTransferProvider — weekly nurse payoutsSeams:BankTransfer:*Real payoutsrow 23
12سامانه مودیان (tax e-invoicing)IMoadianClient — legal invoice registrationSeams:Moadian:* + signing certLegal — soon after launchrow 45
13KYC bridge vendor (Finnotech-class)IShahkarVerifier + IIdentityKycProvider + IBankAccountOwnershipVerifierSeams:Shahkar:*, Seams:IdentityKyc:*, Seams:BankOwnership:*Real verification + payout gaterows 27, 28, 30
14Geocoding (Neshan)IGeocoder — address → coordinates (EVV distance)Seams:Geocoding:*With real EVVrow 31
15Review-moderation classifier (LLM/API)IReviewModerationService — AI pre-screenSeams:ReviewModeration:*Optional (human queue is default)row 33
16MoH / INO / eNamadICredentialVerifier + ILicenseVerificationServicemanual admin process; no public B2B API existsSeams:LicenseVerification:*Manual = the MVP designrows 29, 50
17ElasticsearchINurseSearch alt backend + outbox feederSearch:Backend (non-sql throws today)Not MVP — SQL search is realrows 38, 43

Explicitly not needed (verified absent from server/Directory.Packages.props and code): message broker (no RabbitMQ/Kafka), Redis today (no StackExchange.Redis), Hangfire/Quartz today, Elasticsearch client (Elastic.Clients.*), any cloud SDK, any payment/SMS vendor SDK. The only externally-pointing package beyond SQL Server is Serilog.Sinks.Elasticsearch — its wiring is commented out (Baya.Infrastructure.CrossCutting/Logging/LoggingConfiguration.cs:58-70).


Dependency graph

Solid edges are live today; dashed edges are behind a mocked seam (the arrow exists in code, the wire does not). One line per node below the graph.

Next.js clientHTTPS · JSON (camelCase) Prometheus (+ Grafana)scrapes /metrics + health API HOST · Baya.Web.Api (:5002) ASP.NET Core APIREST /api/v1 · Swagger/metrics · /HealthCheck · gRPC In-proc interval jobsexpiry 1min · retention 24h 18 vendor seams resolve in-process (mocks) today — dashed edges = the wire to build DATA & PLATFORM INFRA SQL Server «Baya»12 schemas · system of record SQL Server «Baya_Logs»Serilog sink (deployed envs) Rediscache + dist. lock — in-proc now MinIO / S3object storage — local disk now MONEY RAILS (ALL MOCKED TODAY) PSP / IPG + Shaparakcapture · webhook · تسهیم BNPLSnappPay / Digipay PAYA / SATNA railweekly nurse payouts سامانه مودیانtax e-invoicing TRUST & IDENTITY RAILS (ALL MOCKED TODAY) SMS gateway (OTP)launch-critical — logs only now KYC bridgeShahkar · e-KYC · استعلام شبا Neshan geocodingEVV distance accuracy Review moderationoptional — human queue default MoH / INO / eNamadmanual admin review — no public API exists HTTPS/JSON scrape EF Core · Serilog cache · lock · files capture · payouts · invoices webhooks / callbacks OTP · استعلام · geocode · moderation LEGEND live today mocked seam — to build service to provision
Mermaid source (canonical, in the .md)
flowchart LR
  subgraph fe[Frontend]
    WEB["Next.js client"]
  end
  subgraph host["API host — Baya.Web.Api (:5002)"]
    API["ASP.NET Core API\nREST /api/v1 · /metrics · /HealthCheck"]
    JOBS["In-proc interval jobs\n(→ Hangfire/Quartz later)"]
  end
  subgraph data[Data & platform infra]
    SQL[("SQL Server 'Baya'\n12 schemas · migrations on boot")]
    LOG[("SQL Server 'Baya_Logs'\nSerilog sink, Warning+")]
    REDIS[("Redis — cache + dist. lock\n(in-proc today)")]
    S3[("MinIO / S3 — object storage\n(local disk today)")]
  end
  subgraph money["Money rails (all mocked today)"]
    PSP["PSP / IPG + Shaparak\ncapture · webhook · تسهیم"]
    BNPL["BNPL — SnappPay / Digipay"]
    BANK["PAYA / SATNA payout rail"]
    MOAD["سامانه مودیان e-invoicing"]
  end
  subgraph trust["Trust & identity rails (all mocked today)"]
    SMS["SMS gateway (OTP)"]
    KYC["Shahkar · e-KYC · استعلام شبا"]
    GEOC["Neshan geocoding"]
    MODAI["Review-moderation classifier"]
    MANUAL["MoH / INO / eNamad\n(manual admin review)"]
  end
  subgraph obs[Observability]
    PROM["Prometheus (+ Grafana)"]
  end
  WEB -->|HTTPS/JSON| API
  API --> SQL
  API --> LOG
  JOBS --- API
  API -.-> REDIS
  API -.-> S3
  API -.-> SMS
  API <-.-> PSP
  API <-.-> BNPL
  API -.-> BANK
  API -.-> MOAD
  API -.-> KYC
  API -.-> GEOC
  API -.-> MODAI
  MANUAL -.- API
  PROM -->|scrape /metrics| API

Per-service notes

1–2 · SQL Server (Baya + Baya_Logs)

3 · Reverse proxy / TLS

4 · Prometheus (+ Grafana)

5 · Redis

6 · MinIO / S3 / ArvanCloud

7 · Job scheduler

8 · SMS gateway

9 · PSP / IPG + Shaparak (تسهیم)

10 · BNPL providers

11 · Bank-transfer rail (PAYA/SATNA)

12 · سامانه مودیان

13 · KYC bridge (Shahkar / e-KYC / استعلام شبا)

14 · Geocoding (Neshan)

15 · Review moderation

16 · MoH / INO / eNamad — a process, not a service

17 · Elasticsearch — deliberately later


Deployment notes (from the code, not aspiration)

  1. Boot = migrate + seed. Every non-Testing start applies EF migrations and seeds roles, the admin/qw123321 user, and an active sandbox ZarinPal gateway (Program.cs:99-104). Until plan §1.3/§1.4/§4.3 land: single-instance start-up, DDL-privileged login, and clean up the seeded credentials per environment.
  2. Environment files: appsettings.jsonappsettings.Development.json (byte-identical); no Production/Staging file exists. All non-secret env differences ride on ~14 Seams:* groups whose defaults live in code (SeamOptions.cs), not in config files.
  3. HTTP posture: HTTP/2-only Kestrel default (plan §1.5), gRPC plugin + reflection always on (plan §7.5), TLS required for JWE sanity.
  4. Single-instance constraints today: in-memory cache, in-proc money lock, in-proc sweeps, per-instance rate-limit buckets. Scaling past one instance requires plan §4.2 (Redis) + §4.3 (migrations) first — the DB uniques keep money correct either way, but locks/cache/limits silently degrade.
  5. Logs: deployed envs write Warning+ to Baya_Logs only (Information dropped — plan §7.3); dev writes console + logs/log.json.
  6. Client: the Next.js app needs NEXT_PUBLIC_API_URL pointing at the proxy; wire casing camelCase; snake_case routes.