← Post-phase server audit

Post-development backend plan — fixes & improvements

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

Audit date: 2026-07-10 · Scope: the completed backend chain (backend-phase-0 → 15) under server/ · Method: read-only audit of code + dev/ docs; every finding cites the file/line it was verified at. Companion documents: frontend-backend-gaps.md (the REQ-by-REQ contract reconciliation) and runtime-services.md (the deployment topology).

The chain is genuinely complete against its own specs: all 16 backend phases shipped, 358 tests are green, and the load-bearing invariants (balanced ledger, DB CHECKs, idempotency uniques, tenancy 404s, forward-only status machines) verifiably exist in code. What remains falls into eight coherent "post-phases", ordered so that each is a runnable unit of work: deployment blockers first, then a code-level money-correctness fix, then the contract batch that unblocks the frontend lane, then the infrastructure and vendor swaps the seam architecture was built for.

BucketThemeBlocking what?
post-phase-1Security & config hygieneAny non-local deployment
post-phase-2Money-path correctness completionLedger ⇄ bank reconciliation
post-phase-3Frontend-unblock contract batch11 of 12 client domains are still mock-primary
post-phase-4Scheduling, locking & multi-instance readinessUnattended operation; >1 API instance
post-phase-5Identity & trust rails go realReal nurses onboarding (OTP, KYC, docs)
post-phase-6Money rails go realReal payments, payouts, tax
post-phase-7Observability, audit & ops hardeningProduction diagnosability
post-phase-8Scale & laterSearch scale, analytics, doc debt

Status legend used below — Current state always cites what the code does today.


post-phase-1 — Security & config hygiene (do before anything is deployed)

Everything in this bucket is small (S) and none of it changes behavior — but each item is a deployment blocker, and two of them are live credential leaks sitting in git today.

1.1 Rotate and remove the committed SQL Server sa connection string

1.2 Replace placeholder JWE signing/encryption keys and field-encryption keys

1.3 Remove or environment-gate the seeded admin / qw123321 user

1.4 Environment-gate the auto-seeded sandbox ZarinPal payment gateway

1.5 Fix the Kestrel HTTP/2-only default

1.6 Make rate limiting proxy-aware and align the two payment webhooks


post-phase-2 — Money-path correctness completion

The ledger invariants verified clean (balanced groups throw at server/src/Core/Baya.Domain/Entities/Payments/LedgerPosting.cs:26,65,178,204; the four DB CHECKs exist — CK_Bookings_AmountSplit, CK_NursePayouts_NetSplit, CK_Refunds_LegSplit, CK_BnplTransactions_SettleSplit — per the EF configs and Migrations/ApplicationDbContextModelSnapshot.cs:345,3543,3842,206). This bucket closes the holes around those invariants.

2.1 Wire the unreachable BNPL/manual refund settlement (dead-end money state) — top code fix

2.2 Add the promised-but-missing FKs on the forward-dep columns

2.3 Extend IAuditable to the admin-decided money & trust entities

2.4 Close the refund channel-execute-before-commit crash window

2.5 Test the untested admin money paths

2.6 Retire the orphaned refund_ticket_required config key


post-phase-3 — Frontend-unblock contract batch

Full field-level detail, evidence, and priority ordering live in frontend-backend-gaps.md. Summary: of the 15 filed REQs, REQ-001 and REQ-015 are effectively done, REQ-010 is a doc fix, and the other 12 are undelivered; 11 of the client's 12 service domains still default to mock-primary, most gated on exactly these items. This bucket is one backend phase-sized batch of small DTO/endpoint additions:

Effort: one M-sized phase overall · Risk: low (additive DTO fields; regenerate dev/contracts/openapi/swagger.v1.json after) · Deps: none — can run in parallel with post-phase-1/2.


post-phase-4 — Scheduling, locking & multi-instance readiness

4.1 Real job scheduler + register the four deferred crons

4.2 Redis for ICacheService + IDistributedLock

4.3 Separate migrations from boot (multi-instance + least privilege)


post-phase-5 — Identity & trust rails go real

Ordered by user impact: nobody can log in without 5.1.

5.1 Real SMS gateway behind ISmsSenderlaunch-critical

5.2 Real Shahkar + e-KYC vendors (IShahkarVerifier, IIdentityKycProvider)

5.3 Real استعلام شبا (IBankAccountOwnershipVerifier)

5.4 Real geocoder (IGeocoder) behind Neshan

5.5 Real object storage (IObjectStorage) — MinIO/S3/ArvanCloud

5.6 Accept manual as the real path for MoH/INO credentials and partner licensing (document, don't build)


post-phase-6 — Money rails go real

The seam shapes are faithful (idempotency keys, server-side re-verify, upsert-first webhooks are already the handler behavior — verified at HandlePaymentWebhookCommand.Handler.cs:31-88), so each swap is an adapter, not a redesign. Do 2.1 first so the BNPL refund path is complete before real money uses it.

6.1 Real PSP/IPG + webhook signatures + تسهیم (IPaymentProvider, IWebhookVerifier, ISettlementSplitProvider)

6.2 Real BNPL adapters (IBnplProvider / IBnplProviderResolver)

6.3 Real PAYA/SATNA payout rail (IBankTransferProvider) + async reconciliation

6.4 Remove IPaymentCaptureSimulator (the registry's own end-state)

6.5 Real Moadian submission + reconciliation (IMoadianClient)

6.6 Decide the partner-center settlement rail (currently: resolver without money)


post-phase-7 — Observability, audit & ops hardening

7.1 Add tracing and consolidate the two metric stacks

7.2 Broaden health checks and split readiness/liveness

7.3 Revisit production log levels and the notification-channel plan

7.4 Audit-log growth & archival

7.5 Decide TicketMessage.Body encryption and the gRPC plugin's fate

7.6 Keep the docs honest (registry + tracker + map)


post-phase-8 — Scale & later (explicitly not MVP)


Suggested sequencing

post-phase-1 (security)  ──┬──►  post-phase-2 (money correctness)  ──►  post-phase-6 (money rails)
                           │
post-phase-3 (contract batch — parallel, unblocks frontend f9–f15)
                           │
post-phase-4 (scheduler/Redis)  ──►  needed by 6.3/6.5 triggers
post-phase-5 (trust rails; 5.1 SMS is launch-critical, schedule early)
post-phase-7 (observability — start anytime, finish before launch)
post-phase-8 (later)

The two items that should not wait for their bucket: 1.1 (rotate the committed sa credentials — today) and 2.1 (the unreachable refund clearing — before any real BNPL/manual refund exists).