From 798fa2f48ee4dd4b3b68882bf8958faca7b8b2f1 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Sun, 31 May 2026 15:08:50 +0400 Subject: [PATCH] docs: sync from backend 896f17f - persist webhook confirmations --- 02 - Data Models/Payment.md | 6 +++--- 03 - API Reference/Payment API.md | 9 +++++---- 04 - Flows/Payment Flow - Scanner.md | 7 +++++-- 09 - Audits/Activity Log.md | 12 ++++++++++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/02 - Data Models/Payment.md b/02 - Data Models/Payment.md index 0baad15..9daa594 100644 --- a/02 - Data Models/Payment.md +++ b/02 - Data Models/Payment.md @@ -6,12 +6,12 @@ aliases: [Payment Record, Escrow, IPayment] # Payment -> **Last updated:** 2026-05-31 — added AMN scanner provider, oracle quote mirror, and Postgres `payment_quotes` linkage. +> **Last updated:** 2026-05-31 — added AMN scanner provider, oracle quote mirror, Postgres `payment_quotes` linkage, and webhook confirmation persistence. 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.80` 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 normal request paths. Backend `2.6.81` 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]]. > [!note] Source > `backend/src/models/Payment.ts:3` — schema definition @@ -52,7 +52,7 @@ Records every monetary movement in the marketplace: buyer pay-ins, seller payout | `blockchain.sender` | String | no | — | — | — | Source address. | | `blockchain.receiver` | String | no | — | — | — | Destination address. | | `blockchain.confirmedAt` | Date | no | — | — | — | When tx confirmed. | -| `blockchain.confirmations` | Number | no | `0` | — | — | Confirmation count. | +| `blockchain.confirmations` | Number | no | `0` | — | — | Confirmation count persisted from transaction-safety verifier evidence, provider payload `confirmations`, or the configured per-chain threshold fallback when a webhook already reports `confirmed`/`completed`. | | `status` | String | no | `pending` | enum: `pending` / `processing` / `confirmed` / `completed` / `failed` / `cancelled` / `refunded` | yes (compound) | Lifecycle status. ⚠️ `confirmed` vs `completed`: only `confirmed` is counted as a successful payment in stats. See status note below. | | `escrowState` | String | no | — | enum: `funded` / `releasable` / `released` / `refunded` / `releasing` / `failed` / `cancelled` / `partial` | — | Escrow lifecycle. Note the intermediate states `releasable` (delivery confirmed, ready to pay out) and `releasing` (payout in flight) between `funded` and `released`. | | `providerPaymentId` | String | no | — | — | yes (sparse) | External provider id for idempotency. | diff --git a/03 - API Reference/Payment API.md b/03 - API Reference/Payment API.md index 50f5c9a..9c2bef8 100644 --- a/03 - API Reference/Payment API.md +++ b/03 - API Reference/Payment API.md @@ -5,7 +5,7 @@ tags: [api, payment, reference, request-network, escrow] # Payment API -> **Last updated:** 2026-05-31 — Postgres integration promotion, oracle quote persistence, AMN scanner rail-switch fix, and partial gasless permit endpoints. +> **Last updated:** 2026-05-31 — Postgres integration promotion, oracle quote persistence, AMN scanner rail-switch fix, webhook confirmation persistence, and partial gasless permit endpoints. The payment surface is split across provider-neutral payment routers, Request Network checkout/webhook routes, derived-destination custody routes, and admin safety routes: @@ -23,7 +23,7 @@ The payment surface is split across provider-neutral payment routers, Request Ne Core model: [[Payment]]. Coordination logic to avoid race conditions when multiple sources update the same payment is in `paymentCoordinator.ts`. > [!warning] Persistence status -> Payment APIs still create/read/update Mongo `Payment` documents on backend `2.6.79`. The Postgres branch adds schemas, repos, migrations, and optional quote persistence, but it is not a full payment-domain cutover. `/api/payment/request-network/intents` can write `payment_quotes` only when `ORACLE_QUOTING_ENABLED=true`; the payment record itself remains Mongo-backed unless future service wiring changes that boundary. +> Payment APIs still create/read/update Mongo `Payment` documents on backend `2.6.81`. The Postgres branch adds schemas, repos, migrations, and optional quote persistence, but it is not a full payment-domain cutover. `/api/payment/request-network/intents` can write `payment_quotes` only when `ORACLE_QUOTING_ENABLED=true`; the payment record itself remains Mongo-backed unless future service wiring changes that boundary. ## Configuration / health @@ -208,6 +208,7 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip **Description:** Request Network posts settlement updates here. The route verifies `x-request-network-signature` over the raw body, deduplicates delivery IDs, evaluates the Transaction Safety Provider, and coordinates the payment/ledger update. **Auth required:** No (signature-protected) **Response:** `200` when processed or duplicate; `202` when accepted but safety checks are pending; `401` for invalid signature. +**Side effects:** For confirmed/completed events, `blockchain.confirmations` is stored from safety verifier evidence, provider payload `confirmations`, or the configured per-chain threshold fallback before the payment/ledger update is emitted. > [!note] RN payout/release/refund routes > `POST /api/payment/request-network/:paymentId/payout/initiate`, `POST /api/payment/request-network/:paymentId/payout/confirm`, `POST /api/payment/request-network/:paymentId/release/confirm`, and `POST /api/payment/request-network/:paymentId/refund/confirm` are registered in `requestNetworkRoutes.ts` but are stub-level implementations. They accept the request and return a 200 but do not yet drive the ledger-gated release/refund orchestration. Use `POST /api/payment/:id/release` and `POST /api/payment/:id/refund` for actual escrow releases. @@ -220,9 +221,9 @@ AMN Pay Scanner is a custom in-house blockchain scanner that replaces the hosted **Description:** AMN Pay Scanner posts settlement confirmations here. The route verifies a `webhookSecret`-based HMAC signature, then runs the Transaction Safety Provider and `PaymentCoordinator` pipeline identical to the RN webhook path. **Auth required:** No (signature-protected via `AMN_SCANNER_WEBHOOK_SECRET`) -**Request body:** `{ intentId, status, transactionHash?, chainId?, ... }` — scanner-specific envelope +**Request body:** `{ intentId, status, txHash?, transactionHash?, chainId?, confirmations?, ... }` — scanner-specific envelope. Current scanner payloads usually use `txHash`; `confirmations` may be omitted once the scanner has already waited for the configured threshold. **Response:** `200` processed; `401` bad signature; `400` missing `intentId` or unknown format; `404` payment not found. -**Side effects:** Same as the RN webhook — updates [[Payment]], advances [[PurchaseRequest]], accepts/rejects offers, emits socket events when safety checks pass. +**Side effects:** Same as the RN webhook — updates [[Payment]], advances [[PurchaseRequest]], accepts/rejects offers, emits socket events when safety checks pass. Backend `2.6.81+` treats scanner `status: "confirmed"` as a settlement status for Transaction Safety Provider evaluation and confirmation persistence; if neither verifier evidence nor payload `confirmations` exists, it stores the configured chain threshold so the dashboard does not show a paid scanner transaction with `0` confirmations. > [!note] Provider value > Payments created via the AMN Pay Scanner have `provider: 'amn.scanner'` in the database. This is distinct from `request.network` and `shkeeper`. diff --git a/04 - Flows/Payment Flow - Scanner.md b/04 - Flows/Payment Flow - Scanner.md index c7e31bc..6e0732f 100644 --- a/04 - Flows/Payment Flow - Scanner.md +++ b/04 - Flows/Payment Flow - Scanner.md @@ -6,6 +6,8 @@ created: 2026-05-30 # Payment Flow — AMN Pay Scanner (In-House) +> **Last updated:** 2026-05-31 — documented backend `2.6.81` confirmation persistence for scanner `confirmed` webhooks. + End-to-end payment flow using the in-house AMN Pay Scanner, replacing the Request Network integration. The scanner is a separate microservice; the backend talks to it over an internal HTTP API. See also: [Scanner Architecture](../01%20-%20Architecture/Scanner%20Architecture.md), [Scanner API](../03%20-%20API%20Reference/Scanner%20API.md) @@ -57,7 +59,7 @@ Authorization: Bearer "tokenAddress": "0x55d398326f99059ff775485246999027b3197955", "destination": "0xSellerWalletAddress", "amount": "10000000000000000000", - "callbackUrl": "https://api.amn.gg/api/payment/scanner-callback", + "callbackUrl": "https://api.amn.gg/api/payment/amn-scanner/webhook", "callbackSecret": "", "confirmations": 12 } @@ -116,13 +118,14 @@ The scanner POSTs to `callbackUrl` with: "amount": "10000000000000000000", "token": "0x55d...", "chainId": 56, + "confirmations": 12, "status": "confirmed" } ``` Header `X-AMN-Signature` = `HMAC-SHA256(body, callbackSecret)`. -The backend verifies the signature, matches the intentId to a Payment record, and marks it paid. +The backend verifies the signature, matches the `intentId` to a Payment record, and marks it paid. Backend `2.6.81+` treats scanner `status: "confirmed"` as final enough to run Transaction Safety Provider checks and persist `blockchain.confirmations`. The stored confirmation count comes from verifier evidence first, then the webhook payload, then the configured per-chain threshold fallback when the scanner has already waited for enough blocks but did not send a raw count. ### Step 6 — Backend acknowledges diff --git a/09 - Audits/Activity Log.md b/09 - Audits/Activity Log.md index 136d30e..06a806d 100644 --- a/09 - Audits/Activity Log.md +++ b/09 - Audits/Activity Log.md @@ -11,6 +11,18 @@ entries on top. Maintained by agents per the rule in `../AGENTS.md`. --- +### 2026-05-31 — backend@896f17f, frontend@fd8e797 — persist webhook confirmations for scanner payments + +**Commits:** backend `896f17f`, frontend `fd8e797` (backend `2.6.81`, frontend `2.7.21`) +**Touched:** +- Backend: `src/routes/amnScannerWebhookRoutes.ts`, `src/services/payment/requestNetwork/requestNetworkRoutes.ts`, `src/services/payment/safety/transactionSafetyProvider.ts`, `__tests__/transaction-safety-provider.test.ts`, `package.json`, `package-lock.json` +- Frontend: `package.json`, `package-lock.json` version bump only. +**Why:** `dev.amn.gg` showed a confirmed AMN scanner payment with `blockchain.confirmations = 0`. Scanner webhooks report `status: "confirmed"`, but transaction safety only evaluated `"completed"` statuses, so no verifier evidence was produced. The webhook routes now persist confirmations from safety evidence, scanner/RN payloads, or the chain confirmation threshold fallback when the provider already says confirmed/completed. +**Verification:** Backend `npm test -- --runTestsByPath __tests__/transaction-safety-provider.test.ts`; backend `npm run typecheck`; backend `git diff --check`; frontend `npx tsc --noEmit --ignoreDeprecations 6.0`; frontend `git diff --check`. Could not inspect the actual `dev.amn.gg` payment row because SSH to `193.180.213.68` rejected the available key. +**Linked docs updated:** [[Payment]], [[Payment API]], [[Payment Flow - Scanner]] + +--- + ### 2026-05-31 — backend@cab0719, frontend@ec2f765 — align request budget validation after Postgres migration **Commits:** backend `cab0719`, frontend `ec2f765` (backend `2.6.80`, frontend `2.7.20`)