docs: sync from backend 2c5c3c7 — pg ledger repo seam
This commit is contained in:
@@ -6,12 +6,12 @@ aliases: [Payment Record, Escrow, IPayment]
|
||||
|
||||
# Payment
|
||||
|
||||
> **Last updated:** 2026-05-31 — added AMN scanner provider, oracle quote mirror, Postgres `payment_quotes` linkage, webhook confirmation persistence, and capped accepted confirmation counts.
|
||||
> **Last updated:** 2026-06-01 — documented the first payment-repo runtime seam for funds ledger appends/balance reads.
|
||||
|
||||
Records every monetary movement in the marketplace: buyer pay-ins, seller payouts, and refunds. The current model is centered on Request Network pay-in, in-house checkout metadata, on-chain transaction verification, escrow state, and provider request IDs. The `provider` and `direction` discriminators let one collection hold incoming buyer payments, outgoing seller releases, refunds, and legacy/other provider records.
|
||||
|
||||
> [!warning] Runtime store
|
||||
> The `Payment` document is still created, read, and updated through Mongoose on normal request paths. Backend `2.6.82` can persist oracle quotes to Postgres `payment_quotes`, but that is conditional on `ORACLE_QUOTING_ENABLED=true` and does not make the whole payment domain PG-authoritative. See [[Postgres Runtime Cutover Status]].
|
||||
> The `Payment` document is still created, read, and updated through Mongoose on most normal request paths. Backend `2.8.20` routes `FundsLedgerEntry` appends and balance reads through the payment repository seam (`REPO_PAYMENT=mongo|dual|pg`), but the default remains Mongo and this does not make the whole payment domain PG-authoritative. Oracle quotes can persist to Postgres `payment_quotes` when `ORACLE_QUOTING_ENABLED=true` and a PG parent payment row can be resolved. See [[Postgres Runtime Cutover Status]].
|
||||
|
||||
> [!note] Source
|
||||
> `backend/src/models/Payment.ts:3` — schema definition
|
||||
@@ -23,12 +23,8 @@ Records every monetary movement in the marketplace: buyer pay-ins, seller payout
|
||||
> [!note] `provider` values
|
||||
> The current backend schema accepts `request.network`, `amn.scanner`, `shkeeper`, and `other`. `amn.scanner` is the in-house scanner provider used for direct on-chain monitoring. Older docs and some frontend types may still mention historical values such as `test` or `decentralized`; treat those as legacy until their active routes are audited again.
|
||||
|
||||
> [!warning] `confirmed` vs `completed` — stats undercount
|
||||
> Payment stats (`paymentService.getPaymentStats`) only increment `successfulPayments` for status **`confirmed`**:
|
||||
> ```ts
|
||||
> case "confirmed": stats.successfulPayments += stat.count; break;
|
||||
> ```
|
||||
> The terminal SHKeeper / DePay state is **`completed`**, which has no case in the switch and is therefore **not** counted as a successful payment. ⚠️ This causes successful-payment stats to undercount any payment that reached `completed`.
|
||||
> [!note] `confirmed` vs `completed` — stats parity
|
||||
> Payment stats should count both **`confirmed`** and **`completed`** as successful. Backend `2.8.20` aligns the Mongo and Drizzle payment repository implementations with that behavior before broader payment-service wiring.
|
||||
|
||||
> [!warning] `SIM_` payment-hash bypass — security concern
|
||||
> In both `payment/paymentRoutes.ts` and `marketplace/routes.ts`, a `paymentHash` that starts with `SIM_` (or a short `0x...` hash under 64 chars) is treated as a simulated transaction and **skips on-chain verification entirely** (`isVerified = true`). There is **no environment guard** (e.g. no `NODE_ENV !== 'production'` check) around this branch, so the bypass is reachable in production. ⚠️ A caller can mark a payment verified without any real on-chain settlement.
|
||||
@@ -126,6 +122,12 @@ Defined at `backend/src/models/Payment.ts:174-188`:
|
||||
|
||||
The Postgres money-core branch can store oracle quotes in `payment_quotes`, a 1:1 child table keyed by `payment_id → payments.id`. Amount/rate columns use `numeric(38,18)` and the route resolves the PG parent through `payments.legacy_object_id` or `id_map` during the Mongo/PG dual-write window. If the PG payment row is missing, the quote is mirrored to this Mongo `quote` subdocument and a `pg_dualwrite_gaps` row is recorded for reconciliation. This table is quote/audit storage only until the payment service itself is wired through the PG repository path.
|
||||
|
||||
## Funds Ledger Repository Seam
|
||||
|
||||
Backend `2.8.20` routes `appendFundsLedgerEntry`, `getFundsBalanceByPurchaseRequestId`, and `getFundsBalanceByPaymentId` through `getPaymentRepo()`. In default mode this is still `MongoPaymentRepo`, preserving the existing `FundsLedgerEntry` collection behavior. `REPO_PAYMENT=dual` can mirror ledger writes to Postgres after backfill/verification; `REPO_PAYMENT=pg` should wait until the surrounding payment services, derived destinations, and webhook/update paths are also wired and soaked.
|
||||
|
||||
The Drizzle ledger balance path supports both UUID entity refs and external/string refs, which matters for template-checkout rows where `purchaseRequestId` or `paymentId` is not a normal Mongo ObjectId.
|
||||
|
||||
## Pre/Post Hooks
|
||||
|
||||
None declared.
|
||||
|
||||
Reference in New Issue
Block a user