Required reading
Dual-Mode Merchant Engine
One deployable URL. Two gates.
Architecture
Environment (ENVIRONMENT=village|live, with legacy sandbox→village and production for Live telecom) configures infrastructure.
Execution mode (VILLAGE | LIVE) is chosen per request:
- Classifier: payment proof → Village; client key → Live; both → reject; neither → 402.
- Gate establishes trust (verify proof or credential).
ExecutionContextflows into every side-effect adapter.
Telecom safety (two gates)
- May *this request* perform live side effects? (
allow_external_side_effects) - Is *this deploy* production with Twilio configured?
Village always records virtual SMS — even on production hosts.
Credentials
Per-client keys (pp_live_…), hash-only storage, revoke/rotate, node scope, idempotency for live calls.
Issue via POST /admin/client-keys with X-Admin-Token.
Response metadata
Every response should say which mode ran (execution.mode, telecom_mode, request_id).
Checklist
- [ ] Ambiguous headers return 400
- [ ] Village unpaid returns 402
- [ ] Production + Village still virtual SMS
- [ ] Live + sandbox stays virtual
- [ ] Live + production without Twilio fails explicitly (not fake success)
- [ ] Idempotent live retries do not double-send
Full template notes: Merchant Template.