vault
09 — Open Questions
Open Questions
Decisions waiting on stakeholders. Each item names the owner, the decision needed, and the target by which we need it.
Mission
Launch market
- Owner: CEO
- Decision: which jurisdiction(s) for soft launch — Estonia, Lithuania, Cyprus, all-EU, or non-EU?
- Target: before 10-Roadmap#Beta
- Why blocked: drives MiCA scope, KYC vendor choice, fiat banking partner.
KPI thresholds
- Owner: PM
- Decision: replace placeholder targets in 01-Overview with board-approved numbers.
- Target: end of MVP cycle.
Custody & Banking
Custody
- Owner: CTO
- Decision: Fireblocks vs Bitgo vs self-custody (HSM).
- Trade-off: vendor cost vs operational complexity vs insurance coverage.
Sell payout rail
- Owner: Finance lead
- Decision: which fiat rail flips
sellorders frompendingtocompleted. SEPA + manual? Modulr? Banking Circle? - Blocking 03-Domains#Sell beta.
Acquirer ✅ resolved (2026-05-03)
- Decision: Mercuryo is the contracted card acquirer + on/off-ramp partner. PCI scope sits with Mercuryo.
- Why: licensed EU CASP, single integration covers card-acquiring + on-ramp + off-ramp + crypto-to-crypto; lets us avoid building a card relationship.
- Follow-ups: SEPA payout rail for Sell still open under Sell payout rail.
AML & Compliance
AML provider ✅ resolved (2026-05-03)
- Decision: Elliptic. One vendor covers wallet-AML risk and address-level sanctions via the same API.
- Why: consolidated AML + sanctions reduces integration surface; well-supported case-management UI for ops; suits MiCA / FATF expectations.
- Engineering: keep
EllipticProviderinterface; cache-aside 24 h per(address, network, currency).
Sanctions ✅ resolved (2026-05-03)
- Decision: delivered via Elliptic (combined product). Lists in scope: OFAC SDN, EU consolidated, UK HMT, UN — Elliptic refreshes them upstream.
- Why: avoids separate Refinitiv-style feed + reconciliation between two vendors.
- Follow-up: confirm per-jurisdiction list additions per launch market with Compliance lead.
KYC vendor ✅ resolved in practice (Sumsub)
- Built:
SumsubService(lib/providers/kyc/sumsub.ts) selected byKYC_MODE=live, with applicant metadata columns (0028_add_sumsub_metadata) and an inbound review webhook at/api/webhooks/kyc. - ⚠️ The decision was never formally ratified here — the integration landed ahead of the sign-off this entry was tracking. Compliance lead should confirm Sumsub against Onfido / Veriff retrospectively, or accept it.
- Remaining: contract + DPA before live signup.
Travel Rule integration
- Owner: Compliance + Eng lead
- Decision: vendor / protocol — Notabene vs Sumsub Travel Rule vs Veriscope vs Shyft vs TRP-direct.
- Trade-off: counterparty-VASP coverage (which regulated counterparties speak the same protocol) vs vendor lock-in vs per-message cost.
- What it gates: any custodial outbound from EU launch — Send, Payouts, API-order settle. EU TFR has no de minimis.
- Required schema additions documented at 15-Compliance#Engineering surface — what this changes.
- Target: before 10-Roadmap#Beta.
Self-hosted wallet handling
- Owner: Compliance + PM
- Decision: when the destination is a self-custodial wallet, do we (a) ask the user to attest "this address is mine" + take a proof, or (b) always treat the receiver as a third-party beneficiary and capture identity for them?
- Why blocked: TFR Art. 14(5) gives both options; option (a) is friendlier to power users, option (b) is friendlier to compliance review.
CASP path
- Owner: Compliance + Finance + CEO
- Decisions (one stack, all need answering before 10-Roadmap#Beta):
- Own license vs co-CASP — file our own CASP application or partner with a licensed CASP (white-label / tied-agent). Trade-off: speed-to-launch + lower capital under co-CASP; product control + margin under own license.
- Class — Class 2 (€125k, custody + exchange + transfer) is the working assumption for the shipped MVP. Moving to Class 3 (€150k, trading platform) only if we add an order-matching surface — not currently in scope.
- NCA / member state — choose the National Competent Authority. Trade-offs: Estonia (FSA, fast, real-substance bar), Lithuania (Bank of Lithuania, English-speaking, heavier scrutiny than pre-MiCA), Cyprus (CySEC, cheap setup, reputation cost), Malta (MFSA, slow, expensive), Ireland (CBI, banking-grade reputation, heavy lift), France (AMF, toughest, best reputation), Germany (BaFin, EU-market-access, heavy substance bar).
- Co-CASP partner shortlist — only relevant if (1) lands on co-CASP. Need to pick 2–3 candidates and run diligence in parallel.
- Hard deadlines:
- 30 December 2024 — MiCA already fully applicable. New entrants need an authorisation before serving EU customers.
- 1 July 2026 — many EU member states require existing local-VASP registrations to file a CASP application by this date. Per-state grandfathering windows differ; this is the latest common cutoff.
- End of 2026 — most national VASP regimes phased out.
- Why blocked: drives the entirety of 15-Compliance, shapes who files DAC8 (DAC8 build), and gates the Travel Rule vendor choice (Travel Rule integration) since the chosen NCA may have a preferred protocol.
Capital plan
- Owner: Finance + CEO
- Decision: how much initial paid-in capital to inject — €125k (Class 2 floor) is the minimum, but real-world filings hold more for risk-weighted exposure (custody float, AML/sanctions reserves, working capital cushion).
- Why blocked: capital adequacy is part of the CASP application and must be demonstrable via audited statements at filing time. NCAs have rejected applications for under-capitalisation despite hitting the legal floor.
- Target: before 10-Roadmap#Beta application filing.
DAC8 build
- Owner: Compliance + Eng lead
- Decision: build in-house vs adopt a CARF-aware vendor (Notabene Tax, BitOK, Tax Bit Crypto). Reporting timeline + ownership.
- Why blocked: DAC8 applies from 1 January 2026; first reporting cycle 2027 covers calendar 2026. The aggregation has to start at year-start of the first applicable year, so this can't be left to the last quarter.
- Schema sketch at 15-Compliance#Engineering surface — what this changes.
Backfill TIN
- Owner: PM + Compliance
- Decision: when (and how) do we collect TIN + tax-residence from users who signed up before DAC8 enforcement? In-product nag, email campaign, or hard-block at next sensitive action?
- Trade-off: friction vs reporting completeness.
Tax & regulatory (legacy entry — see split above)
- This question has been split into Travel Rule integration, DAC8 build, CASP path, Self-hosted wallet handling, and Backfill TIN. Keep the anchor for old links.
PII storage
- Owner: Eng lead
- Decision: encryption-at-rest scope. PII in
usersandpayeesis plain. DAC8-collected TIN must be encrypted at rest — see 15-Compliance#Engineering surface — what this changes. - Scope: auth secrets are app-stored.
users.totp_secretis plaintext today, alongsidepassword_hashandtotp_recovery_code_hash(both hashed, which is correct). The TOTP secret is the one that needs encryption, not hashing, since it must be recoverable to verify.
Engineering
Background queue ✅ largely resolved — pg-boss shipped
- Built:
worker/worker.tsruns a dedicated pg-boss worker over 11 queues (payout.execute,send.submitted,buy.submitted,webhook.deliver,provider.webhook.process,dev-only.provider.webhook.dispatch,mail.send,order.expire.verify/order.expiry.tick,invoice.reminders.tick,fireblocks.poll.pending,reconcile.balances). The in-processrunJobrunner is gone. - Still open: worker topology under load (how many workers, how they're placed in the AWS target), retry/backoff policy per queue, cron ownership, and dead-letter visibility beyond
/admin/jobs.
Webhook resumer ✅ resolved
- Built: delivery runs on the
webhook.deliverpg-boss queue, so retries are durable across deploys, autoscale and crashes rather than living in an in-process loop. Inbound provider callbacks get the same treatment viaprovider_webhook_events+provider.webhook.process. - Still open: the published delivery SLA and dead-letter review surface — tracked at Webhook reliability.
Multi-region
- Owner: Eng lead
- Decision: when to promote Prod from single-region (Multi-AZ) AWS to active-active multi-region. Postgres read replicas + cross-region failover are scoped under the AWS target (11-Target-Architecture).
Payout perf
- Owner: Eng lead
- Decision: ship with sequential per-row execution or pipeline 4–8 in parallel.
Secrets at rest
- Owner: Eng lead
- Decision: encrypt webhook_secret and high-risk PII with a KMS key.
Email deliverability
- Owner: Eng lead
- Decision: Resend is the live transactional sender (
EMAIL_PROVIDER=resend);mockwrites tomock_emails. Postmark remains deferred unless Resend deliverability is insufficient post-warmup.
Oracle ✅ resolved — CEX.IO
- Decision: CEX.IO is the rate source for quotes, invoice rate-freeze and conversion previews.
- Shipped:
CexioOracle(lib/providers/cexio.ts) callinghttps://cex.io/api/last_prices/EURwith a 5 s timeout and a 30 s batch TTL, with stale-on-failure fallback.MockOracleremains the local-development default. - Consideration: CEX.IO does not differentiate USDT/USDC by network —
USDT_ETHandUSDT_TRXresolve to the same ticker. Acceptable for pricing, worth stating explicitly if quotes are ever contested. - Why: broad pair coverage, simple integration, sufficient for launch volumes; behind the
OracleProviderabstraction so any future swap is non-breaking. - Re-evaluate at GA: Kaiko / CryptoCompare / Chainlink — driven by uptime SLA, regional pair coverage, and licensed-feed requirements (esp. for invoice rate-freeze under MiCA).
Outbound network gas economics
- Owner: Finance + Eng lead
- Decision: who funds the on-chain network fee for outbound transactions, and how that cost is recovered per product surface.
- Context: network gas (BTC miner fee, ETH gas, ERC-20 gas paid in ETH, TRX energy/bandwidth, etc.) still has to be paid to broadcast the transaction even when the customer-facing asset is not the gas asset.
- Current payout stance: merchant Mass Payouts are excluded from any per-recipient network-fee commission change. The platform charges merchants only their per-tier percentage on the payout total; there is no per-recipient flat fee charged to the merchant. Payout network gas remains an operator/treasury economics question for Fireblocks live cutover.
- Open framing:
- Keep product-specific policies. Individual Sends can charge or reserve network fee differently from Mass Payouts.
- Unify all outbound fee policy. Simpler accounting, but conflicts with the current Mass Payout product decision.
- Cross-surface funding mechanisms to evaluate:
- Operator-funded vault. A platform-owned hot vault per chain holds gas (ETH for ERC-20 sends, TRX for TRX sends, BTC for BTC sends). Cost is absorbed into the platform's margin. Simplest UX; biggest treasury exposure (gas inventory across N chains, top-up cadence, FX risk on volatile gas markets).
- Pre-funded customer/merchant gas pocket. Users or merchants top up a separate gas balance per chain alongside token balances. More transparent; pushes operational burden onto customers who may not want to think about gas.
- Per-transaction surcharge. Viable for individual Sends only if disclosed clearly; rejected for Mass Payouts by the current "no per-recipient charge" product decision.
- Fireblocks Gas Station / vault auto-top-up. Live integration only; buys time but does not remove the underlying economics question.
- Why blocked: the choice changes (a) the wallet UX (one balance vs two), (b) the platform's working capital requirement at GA volumes, (c) the per-tier percentage we can sustainably charge, and (d) the reconciliation surface (gas spend per chain has to land in TRES).
- Engineering touchpoint:
lib/payouts/network.PAYOUT_FEE_MINOR_BY_ASSETis currently zeroed across the board for payouts; individual Send fee metadata must remain separate from payout fee policy. - Target: before 10-Roadmap#Beta (Fireblocks live cutover).
Individual outbound transfer network-fee commission
- Owner: Finance + Product + Eng lead
- Decision: fix the commission model for individual outbound Send transfers so the user-facing quote separates principal, platform fee, and network fee recovery. This must not change the Mass Payout fee model above.
- Context: single Sends currently quote
amount + network fee + platform fee, but the business rule for network-fee recovery is not final: should Daxchain pass through exact provider-estimated gas, add a spread, use a fixed network-fee schedule, or absorb gas into the platform fee? - Options:
- Exact pass-through. User pays the provider/network estimate with no spread. Most transparent; may leave Daxchain exposed when actual gas exceeds estimate.
- Pass-through plus buffer. User pays estimated network fee plus a configurable safety margin; unused surplus is either refunded or retained as fee income. Needs precise disclosure and reconciliation.
- Fixed fee schedule by asset/network. Predictable UX; can undercharge during congestion and overcharge in quiet markets.
- Absorb into platform fee. Simplest quote surface; weakest margin control for volatile gas assets.
- Non-goal: do not introduce per-recipient network-fee commission for Mass Payouts as part of this decision.
- Engineering touchpoint: individual sends should keep separate metadata for
networkFeeMinorand platform/send fee so TRES can record principal, network fee, and platform fee independently. - Target: before live Fireblocks individual Send cutover.
Gas asset funding for token transfers
- Owner: Finance + Custody ops + Eng lead
- Decision: how wallets obtain and manage the required gas asset when transferring a token that cannot pay its own network fee, e.g. USDT/USDC on Ethereum require ETH for gas.
- Context: a user may hold enough
USDT_ETHto send the token but no ETH in the same custody wallet. Fireblocks can only broadcast the ERC-20 transfer if the source vault has enough ETH or another approved gas-funding mechanism is available. - Options:
- User-maintained gas balance. Require users to hold ETH/TRX/etc. for token sends on the same network. Clear custody accounting; worse UX.
- Operator gas station / auto-fuel. Platform funds gas assets into source vaults or via Fireblocks Gas Station. Better UX; requires treasury limits, alerts, top-up policy, and abuse controls.
- On-demand gas conversion. Convert a small part of the user's token or other balance into the gas asset before broadcast. Complex, adds price/slippage and regulatory/accounting questions.
- Block token send until gas is available. Safest implementation; creates failed-send support load unless the UI explains the shortfall before confirmation.
- Product requirement: the quote/confirm UI must show both "asset being sent" and "gas asset required" when they differ, including a clear error when the gas asset is missing.
- Reconciliation requirement: actual gas spend must land in the ledger/TRES as network fee in the gas asset, not silently netted from the token principal.
- Target: before live ERC-20 Send cutover.
Target architecture
TRES alignment
- Owner: CTO + Finance
- Decision: scope of TRES vs Postgres-side accounting. Keep TRES purely for accounting interpretation, or also as the operational ledger?
- Why blocked: shapes the cutover plan in 11-Target-Architecture and the reconciliation runbook in 14-Operations.
- Target: before 10-Roadmap#Beta.
AWS edge hardening
- Owner: Eng lead
- Decision: when we promote the MVP ALB + regional WAF entry to the full AWS-native edge stack (Route 53 + CloudFront + AWS WAF + AWS Shield in front of API Gateway) and onboard admin to AWS IAM Identity Center (SSO + MFA) with a dedicated AWS WAF ruleset.
- Trade-off: full edge security posture vs hardening cost (DNS change, traffic re-pointing, edge cache warm-up).
- Target: pre-Beta.
CoSigner topology
- Owner: Eng lead
- Decision: Dev CoSigner profile — sandbox-only or simplified production-like? Final per-AZ topology in Test/Prod?
- Why blocked: drives 12-Environments sizing and 13-Network-Model SG-COSIGNER scope.
NAT topology
- Owner: Eng lead
- Decision: Multi-AZ NAT vs single NAT in Test (Prod is Multi-AZ regardless).
- Trade-off: cost vs failure-domain reduction.
Sizing
- Owner: Eng lead
- Decision: final compute + DB sizing per environment.
- Why blocked: drives the 10-Roadmap#Beta cost envelope.
Admin & merchant scope
Admin role split
- Owner: PM + COO
- Decision: do all admins get all sections, or split into roles (support / finance / risk / engineering)?
- Why blocked: 14-Operations#Privileged actions presumes role-based gating; the split needs ownership.
- Target: before 10-Roadmap#GA.
Subaccount revocation
- Owner: PM
- Decision: when a parent merchant is disabled, what happens to active subaccount sessions and pending invitations? Hard cut, grace period, or per-action recheck?
- Surface: 03-Domains#Subaccounts.
Product
Refunds
- Owner: PM
- Decision: refund flow for buy orders that settle but customer disputes the card charge.
Webhook reliability
- Owner: PM + Eng
- Decision: SLA + backoff for
webhook_events. Pre-GA we should publish: ≥99.9% delivery within 24h, exponential backoff to 7d, dead-letter view.
Admin gaps
- Owner: PM
- Decision: scope of bulk export, refund/reverse affordances, notification preferences UI.
Fee schedule public commitment
- Owner: PM
- Decision: do we publish the per-tier fee schedule on a marketing page? If yes, tier edits become a marketing/legal change.
Customer dispute resolution
- Owner: COO
- Decision: in-product ticket flow vs Zendesk integration vs email-only.