# Runbook — Payments (sandbox PSP)

## Model
TRA uses a **sandbox adapter** (no PAN stored). Checkout sends only a test-card last-4 selector to TRA; live PSPs must use hosted fields / redirect.

## Env
- `SANDBOX_WEBHOOK_SECRET` — HMAC secret for `POST /webhooks/sandbox/payments` (`X-Sandbox-Signature`).
- Feature flag `checkout_enabled` — disable to roll back browse/RFQ-only.

## Payment failures
1. Customer sees decline message (test card `0002`).
2. Inventory reservations for the checkout are **released**.
3. Payment row status → `failed`. Retry: update checkout and pay again (new intent idempotency key includes total).

## Capture
Sandbox confirms as captured (`paid`) immediately after successful confirm. Fraud `hold` blocks pay until admin clears review.

## Refunds
Admin order detail → Refund (`amount_cents`, optional restock). Partial refunds update `payment_status` to `partially_refunded` / `refunded`. Restock appends inventory adjust movements.

## Webhook idempotency
Events keyed by `(provider, event_id)`. Duplicates return `{duplicate:true}` without reprocessing.

## PCI SAQ note
Hosted / redirect / sandbox only — **no raw card data in logs or DB**. Prefer SAQ A / A-EP with production PSP.
