Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The smaller set of general project documents stays directly in `docs/`:
| [`operations-monerium-interface.md`](operations-monerium-interface.md) | Monerium onramp boundary across the OAuth and white-label apps plus the profile, address, IBAN, and payment interface reference |
| [`operations-testing.md`](operations-testing.md) | Maintained test strategy and suite boundaries |
| [`product-dashboard.md`](product-dashboard.md) | Current dashboard product scope and acknowledged gaps |
| [`product-monerium-b2b-flow.md`](product-monerium-b2b-flow.md) | High-level end-to-end flow of the Monerium B2B onramp for Vortex, SulPayments and Monerium, with the open questions per party |
| [`product-monerium-b2b-flow.md`](product-monerium-b2b-flow.md) | High-level end-to-end flow of the Monerium B2B onramp for Vortex, the partner and Monerium, with the open questions per party |
| [`proposal-mcp-server.md`](proposal-mcp-server.md) | Active, non-authoritative discussion draft |
| [`proposal-monerium-consumer-onramp.md`](proposal-monerium-consumer-onramp.md) | Phase-2 proposal for the consumer (Safe + passkey) Monerium onramp; the B2B variant shipped |
| [`proposal-api-driven-kyc-kyb.md`](proposal-api-driven-kyc-kyb.md) | Proposal for API-driven verification using preserved provider-specific workflows |
Expand Down
4 changes: 2 additions & 2 deletions docs/adr-0005-monerium-b2b-onramp.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ consumer-flow design this grew out of remains a phase-2 proposal:

## Context

Partner-sourced business clients (SulPayments' OTC corporates, KYB'd under the partner's
Partner-sourced business clients (the partner's OTC corporates, KYB'd under the partner's
FINMA/VQF licence with per-customer reliance attestations to Monerium) need EUR → USDC
on Ethereum with **zero Vortex-side interaction**: no app, no wallet ceremony, no digital
signature. Onboarding is paperwork only. The single blocker in the consumer design was
Expand Down Expand Up @@ -144,7 +144,7 @@ not yet deployed, so this replaced the flat fee before launch with no migration)

## Amendment 2026-09-17: whole-deposit settlement and the refund path

Product requirements from the partner (SulPayments): one USDC transfer per bank
Product requirements from the partner: one USDC transfer per bank
payment, and an automatic refund of the exact EUR amount to the payer's bank account
when a payment cannot be converted inside the promised window. Vortex holding the funds
for that refund is agreed commercially. Decisions (the proposal that led here,
Expand Down
8 changes: 4 additions & 4 deletions docs/operations-monerium-b2b-rollout.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ verbal/Telegram statements; consolidate into the MSA or a side letter:
6. SEPA recall / fraud loss allocation after conversion+forwarding.
7. Per-IBAN suspension capability for incident response.
8. Corporate KYB mechanism for direct (non-reliance) clients — not needed for the
SulPayments pilot, still an MSA item.
partner pilot, still an MSA item.
9. Advance notice of any change to the EIP-1271 ownership/link message (and the
recovery message): the forwarder whitelists their exact hashes, so an unannounced
change fail-closes new onboarding.
Expand All @@ -41,7 +41,7 @@ the subsidy vault (P13).
**G3 — external contract audit.** Parameters are final (ADR); the internal reviews and
the invariant suite are done, but this moves client funds.

**G4 — pilot.** SulPayments agreement signed (terms inputs below), reliance
**G4 — pilot.** Partner agreement signed (terms inputs below), reliance
attestations per customer, 3–5 clients at **€50k/client/day** (paper control), launch
fee policy 12.5 bps target / 15 bps floor (B1).

Expand Down Expand Up @@ -89,7 +89,7 @@ The Sepolia sandbox follows its own procedure in the runbook (§8).
Receive → "Simulate bank transfer") and re-verify the signed `webhook-id`,
`webhook-timestamp`, and `webhook-signature: v1,<base64>` fixture against a real
production delivery.
9. SulPayments side: manager profile configured (EU corridor, business type), secret
9. Partner side: manager profile configured (EU corridor, business type), secret
credential issued, deposit-event webhook registered and verifying signatures against
`GET /v1/public-key`.
10. Confirm every mapped forwarder has a zero EURe balance before the first enablement.
Expand Down Expand Up @@ -199,7 +199,7 @@ The Sepolia sandbox follows its own procedure in the runbook (§8).
| G1 package (9 items) | Marcel ↔ Monerium | All verbal; consolidate in writing |
| G2 legal scope | Counsel | Not started |
| G3 audit | External | After PR merge; params final |
| SulPayments agreement (terms above) | Marcel ↔ partner | Drafting inputs ready |
| Partner agreement (terms above) | Marcel ↔ partner | Drafting inputs ready |
| Sandbox SEPA simulation + 3 TODO(sandbox) pins | Engineering (needs Marcel's sandbox login) | Open — only remaining engineering unknown |
| Fee Safe multisig creation | Ops | Before implementation deploy; also the subsidy vault's treasury |
| Reference wording in the partner agreement | Marcel ↔ partner | Agreement says "Coinbase EURC oracle"; implementation uses the Coinbase Exchange EURC-USDC bid/ask midpoint (spot, since 2026-09-18) — confirm that is what was meant |
Expand Down
16 changes: 8 additions & 8 deletions docs/operations-monerium-b2b-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ On the `vortex-sandbox` service only:
| Variable | Value |
|---|---|
| `FLOW_VARIANT` | `mykobo` (startup refuses B2B otherwise; the sandbox's retail EUR onramp then runs on Mykobo) |
| `MONERIUM_WHITELABEL_CLIENT_ID`, `MONERIUM_WHITELABEL_CLIENT_SECRET` | SulPayments' sandbox white-label app (S11) |
| `MONERIUM_WHITELABEL_CLIENT_ID`, `MONERIUM_WHITELABEL_CLIENT_SECRET` | The partner's sandbox white-label app (S11) |
| `MONERIUM_B2B_RPC_URL` | Sepolia RPC |
| `MONERIUM_B2B_FORWARDER_FACTORY_ADDRESS` | `$FACTORY` |
| `MONERIUM_B2B_KEEPER_PRIVATE_KEY`, `MONERIUM_B2B_GUARDIAN_PRIVATE_KEY`, `MONERIUM_B2B_ATTESTOR_PRIVATE_KEY` | the three keys of §8.3 |
Expand All @@ -896,7 +896,7 @@ On the `vortex-sandbox` service only:
| `MONERIUM_B2B_WEBHOOK_SECRET` | `whsec_` plus base64 of 32 random bytes: `echo "whsec_$(openssl rand -base64 32)"` |
| `MONERIUM_B2B_ENABLED` | `true`, set last |

Register Vortex's webhook subscription on SulPayments' sandbox app with the same
Register Vortex's webhook subscription on the partner's sandbox app with the same
secret, from `apps/api` with that app's credentials and `MONERIUM_API_URL` pointing at
Monerium's sandbox API:

Expand All @@ -914,18 +914,18 @@ Restart the service. Startup fails if a required setting is missing; once it is

### 8.7 Partner and test clients

1. Make SulPayments' sandbox profile a manager:
1. Make the partner's sandbox profile a manager:
`PUT /v1/admin/managed-profile-managers/<profileId>` with corridor `EU` and customer
type `business`. SulPayments then takes a key from dashboard-sandbox and registers
type `business`. The partner then takes a key from dashboard-sandbox and registers
its webhook through `POST /v1/webhook` (`DEPOSIT_UPDATED`, `ACCOUNT_UPDATED`).
2. Per test client, once SulPayments confirms the Monerium profile is approved: §1.2
2. Per test client, once the partner confirms the Monerium profile is approved: §1.2
(refund address, deploy the clone), §1.4 (map), §1.5 (automatic link and IBAN),
§1.7 (activate). Until the destination endpoint (V6) exists, SulPayments sends the
§1.7 (activate). Until the destination endpoint (V6) exists, the partner sends the
profile ID and the Sepolia destination to Vortex directly.

### 8.8 Test payments

SulPayments simulates each SEPA payment on the client's profile in its Monerium sandbox
The partner simulates each SEPA payment on the client's profile in its Monerium sandbox
app ("Simulate bank transfer"); EURe lands on the clone and the keeper takes over.

| Test | Payment | Expected |
Expand All @@ -934,7 +934,7 @@ app ("Simulate bank transfer"); EURe lands on the clone and the keeper takes ove
| Chunked | €60 | Three chunks at the €25 cap, then one forward of their sum |
| Refund | €15 | Suspend the account before the payment (`PATCH /v1/admin/monerium-b2b/accounts/<accountId>/status` with `suspended`): the keeper converts nothing for a suspended account but still arms the clone's clock and runs recoveries. After two hours the deadline job marks the deposit, the keeper recovers it, and the refund leaves from the client's IBAN. Reactivate afterwards. If the simulated transfer carries no payer IBAN and name, the refund parks as `recovery_failed`; that is a finding about the sandbox simulation, closed with `PATCH /v1/admin/monerium-b2b/deposits/<depositId>/status` |

`DEPOSIT_UPDATED` reports every step to SulPayments, and `GET /v1/monerium-b2b/deposits`
`DEPOSIT_UPDATED` reports every step to the partner, and `GET /v1/monerium-b2b/deposits`
shows the same snapshots.

### 8.9 Re-centre the pool before a session
Expand Down
Loading
Loading