Integration
1. Sister Services
| Sister | Direction | Surface | Auth | Failure Mode | Idempotency |
|---|---|---|---|---|---|
@nx/mq-pay | ← | HTTP webhook /webhooks/payment | none (trusted) | MQ-Pay retries 5xx | webhook handlers no-op on already-applied transitions |
@nx/inventory | → | Kafka payment.success | — | post-commit fire-and-forget | per (saleOrderId, stockId) consumer-side |
@nx/inventory | → | Kafka kitchen-ticket-item.status-changed | — | post-commit fire-and-forget | per (saleOrderId, kitchenTicketItemId, materialId) consumer-side |
@nx/inventory | ← | Kafka material.stock-changed | — | (sale not currently consumes — produced for UI consumers) | — |
@nx/finance | → | Kafka payment.success | — | post-commit fire-and-forget | per saleOrderId consumer-side |
@nx/commerce | → | HTTP — read ProductVariant, ProductInfo, SaleChannel, Category for snapshots | JWT (service-to-service) | retry 3x | snapshot stored on order |
@nx/pricing | → | HTTP — PricingNetworkService.calculate() + calculateV2() | JWT | retry; checkout fails on persistent error | checkout request idempotent (no side-effect on retry) |
@nx/identity | → | HTTP — JWT verification via JWKS (/jw-certs) | JWT | retry / circuit-break | request-id propagated |
@nx/identity | → | HTTP — PolicyDefinitionService permission lookup | JWT | Redis cache fallback | per (role, action) |
@nx/signal | → | WebSocket emission via ApplicationWebSocketComponent | — | best-effort delivery | broadcast |
2. External Systems
Direct external integrations: none. Sale uses MQ-Pay (sister) for payment provider abstraction. Third-party payment providers (VNPay, etc.) are owned by @nx/mq-pay.
3. Critical Cross-Service Flows
3.1 Payment Success → Stock Deduct + Finance Income
Contract:
- Sale guarantees
PAYMENT_SUCCESSis emitted exactly once per status transition (post-commit). - Webhook is the source-of-truth for status — Sale does not poll MQ-Pay.
- Idempotency: webhook handler short-circuits if order already at target status.
3.2 Kitchen Item READY → Material Consume
3.3 Checkout Pricing Fan-out
3.4 MQ-Pay Webhook Retries (Sale's safety net)
4. Contract Stability
| Surface | Stability | Versioning |
|---|---|---|
HTTP /v1/api/sale/* | stable | URL prefix /v1/ |
HTTP webhook /webhooks/payment | stable | request schema versioned via eventType namespace |
Kafka topic payment.success | stable | payload field-additive only |
Kafka topic kitchen-ticket-item.status-changed | stable | payload field-additive only |
WebSocket topics observation/sale/* | stable | payload field-additive |
5. Cross-cutting concerns
| Concern | Handling |
|---|---|
| Trust boundary | Webhook endpoint trusts MQ-Pay (no auth). Network-level isolation via Cilium policy enforces this. |
| Race protection | SELECT FOR UPDATE on order rows during checkout + add-item. |
| Snapshot capture | At checkout, sale snapshots: pricing (v1+v2), allocation state, product variant metadata, recipe id. Lifetime = order. |
| Currency | Stored at order level. Multi-currency requires exchangeRate snapshot per order. |
6. Related Pages
- API Events
- Payment Webhooks — webhook flow detail
- Decisions