Memory Appendix
Vendor Chaos And Tests
Every new vendor adapter (direct_topup, vouchers, esim, payouts) must add a mocky-balboa route with chaos hooks AND ship contract + service tests in the same PR
Source memory file:
feedback_vendor_chaos_and_tests.md· Category: Feedback / working-preference This is a verbatim dump of Claude's persistent memory for the Octopus project. Rendered inside a code block so nothing is altered.
---
name: New vendor implementations need chaos in mocky + proper tests in octopus
description: Every new vendor adapter (direct_topup, vouchers, esim, payouts) must add a mocky-balboa route with chaos hooks AND ship contract + service tests in the same PR
type: feedback
originSessionId: 4a756616-78f2-4e8f-a906-fd34e36a1824
---
When adding a new vendor adapter under `services/external_vendors/` (any of `direct_topup/`, `vouchers/`, `esim/`, `payouts/`, `webhooks/`), the vendor is not "done" until **both** of the following are also delivered in the same PR:
1. **mocky-balboa route** at `frontend/mocky-balboa/src/routes/<vendor>.ts` exposing every endpoint the Go adapter calls. Hosted at `https://mocky-balboa.octopuscards.io/<vendor>`. Must include the real signing/auth flow (HMAC, Svix, bearer, whatever the vendor uses) so adapter signature code is exercised, not bypassed.
2. **Chaos hooks in the mocky route** so fault paths are testable. At minimum:
- Forced 4xx (auth failure, validation, not-found)
- Forced 5xx (server error, gateway timeout)
- Slow response (delay past the adapter's HTTP timeout, ~30s default)
- Malformed body (invalid JSON, wrong content-type, truncated)
- Connection drop mid-response
Pattern: `POST /<vendor>/_chaos { "next_response": {...} }` queues one synthetic failure for the next call. Keep it scoped per-vendor, not global.
3. **Octopus tests** in four tiers (see [feedback_repo_test_coverage](feedback_repo_test_coverage.md) for the equivalent rule on the repo layer):
- **Unit** — error classification (`IsRetryable`, `IsFinal`, `IsTerminal`) for every documented vendor error code.
- **Contract** (`<vendor>_contract_test.go`, build-tagged) — pointed at mocky URL, covers happy path for catalog/order/status/webhook + every chaos shape from #2.
- **Service-level** — narrow-interface fakes test the calling service's reaction (retry, refund, terminal-fail) when the adapter returns each error class.
- **Orchestration** (`<vendor>_orchestration_test.go`, build-tagged with `orchestration`) — full HTTP→handler→adapter→mocky chain. See [project_orchestration_test_harness](project_orchestration_test_harness.md). Runa is the reference; copy its 28-subtest structure when adding a new vendor.
**Why:** Critical system, single dev. Vendor outages are the single biggest cause of customer-visible failures; without chaos coverage we only find out the adapter mishandles a 503 in production. Mocky-balboa is always running and the adapter base URL is already config-driven, so the only thing standing between us and full coverage is discipline in the PR. Past vendor mappers shipped without `MinAmount`/`MaxAmount`/`VendorDiscount` ([feedback_vendor_amount_discount](feedback_vendor_amount_discount.md)) — same pattern, missing test was the leading indicator.
**How to apply:**
- Reviewing or writing a PR titled "add <vendor>" or "wire up <vendor>": block merge if the mocky route, chaos hooks, or any of the three test tiers is missing.
- When extending an *existing* adapter with a new endpoint or product type, the same rule applies for that endpoint — add it to the mocky route, add a chaos case, add a contract test row.
- Don't add speculative branches — only mock and test product types we actually consume ([feedback_no_speculative_vendor_paths](feedback_no_speculative_vendor_paths.md)).
- Vendors not currently in mocky-balboa (Bamboo, Tillo/iRewardify, kgen, voucherkart, wupex, lootbar, trs, ledig payouts) are technical debt — adding them to mocky should accompany the next material change to those adapters.Vendor Amount Discount
Every direct_topup vendor mapper must populate MinAmount, MaxAmount, and VendorDiscount on types.Product — these fields drive pricing, margin, and the variant U
Client Portal Deploy
Client portal (frontend/client/, Next.js) is deployed to Cloudflare Pages, not via the systemd deploy scripts in deploy/