docs: partner provisioning API contract, routing context, Track P
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
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:
@@ -2,7 +2,7 @@
|
||||
|
||||
Companion to [PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md](../PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md) Phase 1 (Sprints 1.1–1.4) and [PRODUCT-PLAN-v3.1-GAP-ANALYSIS.md](../PRODUCT-PLAN-v3.1-GAP-ANALYSIS.md) §3.3/§3.5/§3.6.
|
||||
|
||||
**Status: unblocked (2026-08-17).** [BACKEND-API-REFERENCE.md §7](../../BACKEND-API-REFERENCE.md) previously marked the cart/payment call chain frozen. Per the delivery plan's Sprint 0.1 decision, the freeze is lifted — this contract can move to implementation once backend ownership (also Sprint 0.1, still open) is confirmed.
|
||||
**Status: unblocked (2026-08-17).** [BACKEND-API-REFERENCE.md §7](../../BACKEND-API-REFERENCE.md) previously marked the cart/payment call chain frozen. Per the delivery plan's Sprint 0.1 decision, the freeze is lifted — this contract can move to implementation. Backend ownership was answered 2026-08-18 — a separate backend developer builds against it.
|
||||
|
||||
This doc is the frontend's ask, in the same style as `BACKEND-API-REFERENCE.md`. It does not prescribe backend implementation (DB schema, service boundaries) — only the wire contract and the invariants the frontend needs to hold.
|
||||
|
||||
@@ -204,6 +204,33 @@ Idempotency-Key: <checkoutSessionId>
|
||||
|
||||
A retried call with the same `checkoutSessionId` must return the existing order, not create a second one. This is the mechanism that makes "double-click doesn't create two orders" true regardless of frontend debouncing.
|
||||
|
||||
### 6.5 Routing context
|
||||
|
||||
Added 2026-08-18. Full definition in [PARTNER-PROVISIONING-API-CONTRACT.md §7](PARTNER-PROVISIONING-API-CONTRACT.md).
|
||||
|
||||
```ts
|
||||
interface RoutingContext {
|
||||
companyId: string;
|
||||
routingPath: string[]; // ordered node ids, root -> leaf
|
||||
leafNodeId: string; // the payment point money is accepted at
|
||||
environment: 'TEST' | 'LIVE';
|
||||
merchantReference: string; // partner-supplied, opaque, echoed on every related event
|
||||
providerPaymentId: string; // our payment id, stable, unique
|
||||
}
|
||||
```
|
||||
|
||||
`RoutingContext` is a **required** field on `CheckoutSession`, `PaymentIntent`, and `Payment`. `PaymentEvent` does not carry its own copy — it inherits via `paymentIntentId` — but every event **emitted** to the bus or to a partner must include the resolved context so consumers never need a second lookup.
|
||||
|
||||
Invariants:
|
||||
|
||||
1. Resolved and frozen at checkout-session creation. Immutable for the life of the payment. Later node status changes never rewrite it.
|
||||
2. `routingPath` must resolve to exactly one leaf. Ambiguous or unresolvable → reject at creation. Never accept a payment and resolve routing during reconciliation.
|
||||
3. A payment whose leaf node is `suspended` or `disabled` is rejected at creation.
|
||||
4. `merchantReference` is stored verbatim, never parsed, never normalized.
|
||||
5. `environment` must match the credential's environment. Mismatch is `403`.
|
||||
|
||||
**This is why it lands now, not later.** Without it, a payment cannot be attributed to a store, and §5's reconciliation goal — reconstructing why a given amount was charged — stops one level short of who it was charged for. Adding a routing dimension to a populated payments table after launch is materially more expensive than carrying it from the first row.
|
||||
|
||||
---
|
||||
|
||||
## 7. What the frontend will stop doing once this ships
|
||||
@@ -226,4 +253,4 @@ A retried call with the same `checkoutSessionId` must return the existing order,
|
||||
1. **Payment chain freeze — lifted.** §5 can proceed.
|
||||
2. **FX rate source/provider — ours, in-house, as the default (not just a fallback).** No external provider committed. Backend computes and serves the quote itself; the `source` field in §3.1 can legitimately read `"internal"` as the normal case. Revisit if an external provider is chosen later — the contract shape doesn't need to change, only the value of `source`.
|
||||
3. **Backend-converted prices vs. frontend-requested display currency — still open, needs confirmation before implementation.** This doc's §5.2 models the frontend sending a target `currency` and the backend returning the converted total. Confirm this is the intended flow before backend implementation starts.
|
||||
4. **Backend ownership — still open.** This contract is ready regardless of who builds against it, but implementation can't be scheduled until this is answered.
|
||||
4. **Backend ownership — answered 2026-08-18.** A separate backend developer implements against this contract. Note §6.5: `RoutingContext` must be carried from the first payment row, not retrofitted.
|
||||
|
||||
Reference in New Issue
Block a user