docs: partner provisioning API contract, routing context, Track P
Some checks failed
Architecture Governance / architecture (push) Has been cancelled

A partner integration request landed for programmatic merchant-hierarchy
management (Company/Project/Store/PaymentPoint). Built the answer generically:
partner-specific behaviour is a PartnerProfile config row, and no partner name
appears in any entity, field, endpoint or status value.

New:
- docs/backend/PARTNER-PROVISIONING-API-CONTRACT.md - hierarchy, idempotency,
  node-scoped public-key credentials, TEST/LIVE partition, routing context
- docs/context/adrs/ADR-0003-generic-partner-provisioning-api.md

Amended, because the schema impact must land before Phase 1 is implemented:
- Phase 1 gains RoutingContext on CheckoutSession/PaymentIntent/Payment,
  frozen at checkout-session creation and immutable after
- Phase 7 gains routing on Refund/ReconciliationRecord, plus the rule that
  seller settlement splits happen after routing, never as a hierarchy level
- Phase 9 gains Company/Project above Marketplace and PaymentPoint below it,
  with a backfill sequence for existing marketplaces
- Track S gains partner credentials: public key only, node-scoped authority,
  rotation with overlap, immediate revoke, audit coverage

Also: Track P (P1-P10) in the delivery plan, and backend ownership closed as
answered across the contract set.

Card payment was checked, not added - qr and card both already ship in
cart.component.ts with separate create paths and status pollers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-08-18 11:22:24 +04:00
parent 551a22a245
commit 71da5a8d80
11 changed files with 560 additions and 10 deletions

View File

@@ -19,9 +19,12 @@ interface Refund {
status: 'requested' | 'approved' | 'processing' | 'completed' | 'failed';
requestedAt: string;
completedAt?: string;
routing: RoutingContext; // copied verbatim from the original Payment, never recomputed
}
```
A refund always carries the routing context of the payment it reverses. It is copied, not re-resolved — a store suspended after the payment must still be refundable.
```
POST /api/admin/v2/orders/{orderId}/refunds { orderLineIds, amount, reason }
GET /api/admin/v2/orders/{orderId}/refunds
@@ -43,6 +46,7 @@ interface ReconciliationRecord {
resolvedBy?: string;
resolvedAt?: string;
resolutionNote?: string;
routing: RoutingContext; // from the Payment; makes every row attributable to one payment point
}
```
@@ -56,10 +60,12 @@ Process (per plan §7.3):
```
```
GET /api/admin/v2/reconciliation/queue?marketplaceId=&result=
GET /api/admin/v2/reconciliation/queue?marketplaceId=&companyId=&projectId=&leafNodeId=&result=
POST /api/admin/v2/reconciliation/{id}/resolve { note }
```
Step 3's `merchant_reference` strategy matches on `RoutingContext.merchantReference` — the partner-supplied value, stored verbatim (Phase 1 §6.5). The queue is filterable at every hierarchy level so an unmatched set can be narrowed to one payment point without a join the backoffice has to build itself.
## 3. Settlements
```ts
@@ -78,9 +84,23 @@ interface Settlement {
```
GET /api/seller/v1/finance/settlements
GET /api/admin/v2/finance/settlements?sellerId=&period=
GET /api/admin/v2/finance/settlements?sellerId=&companyId=&projectId=&storeId=&period=
```
### 3.1 Seller split happens after routing
Added 2026-08-18. `Seller` is deliberately **not** a level in the partner hierarchy ([PARTNER-PROVISIONING-API-CONTRACT.md §10.2](PARTNER-PROVISIONING-API-CONTRACT.md)). Order of operations:
```
payment -> routed to exactly one payment point (Phase 1 §6.5, frozen at checkout)
-> reconciled at that payment point
-> split across the sellers whose lines the order contains (this phase)
```
- A `Settlement` belongs to one seller **within one store**. A seller trading in two stores gets two settlements per period, never one merged row.
- Splitting never rewrites `RoutingContext`. The money arrived at one payment point; the split decides who is owed from it.
- `grossAmount` summed across a store's settlements for a period must reconcile against that store's matched reconciliation rows for the same period. A mismatch is a reconciliation defect, not a rounding tolerance.
## 4. Provider breadth (open business question)
Current flow supports QR and card only, via one custom provider integration. Adding wallets/BNPL is an explicit open business decision (not answered in Sprint 0.1) — this contract's `PaymentIntent`/`Payment` shapes from Phase 1 §6 are provider-agnostic already, so a new provider is a new adapter behind the same state machine, not a schema change. No action needed here until that business decision is made.