Appearance
Commerce OS Architecture
Commerce OS is the off-chain operating layer for one-time merchant payments. It complements Vela Protocol; it does not replace the mandate primitive or treat a Solana signature as a business record.
System Boundary
| Concern | Owner |
|---|---|
| Merchant API, D1 records, verification, reconciliation, exports, audit, outbox | vela-dashboard |
Public /pay/:id experience, QR, wallet action, status polling, receipt return | vela-checkout |
| Public TypeScript types and merchant client methods | vela-sdk |
| Merchant-side HMAC verification and event schemas | vela-webhook |
| Invoice, receipt, refund receipt, and credit-note PDFs | Dashboard document pipeline and R2 |
| Transactional receipt email presentation and transport | vela-mail |
Subscription Checkout Sessions remain plan-based and finish by creating a mandate. One-time Payment Intents finish only after strict RPC verification of a public SPL or Token-2022 transfer.
Payment Flow
- An owner, admin, or scoped API key creates a direct Payment Intent, or an unpaid invoice creates/reuses its active intent.
- The dashboard snapshots devnet cluster, mint, token program, decimals, settlement owner and token account, amount, reference public key, expiry, customer, and redirect policy.
- Checkout requests the Solana Pay URI and presents the verified merchant identity. Browser input cannot select the cluster or settlement destination.
- The wallet broadcasts the transfer. Its signature is a lookup hint, not proof.
- The dashboard fetches the confirmed transaction and verifies success, reference, mint, token program, gross amount, recipient token account, settlement owner, and Token-2022 transfer-fee semantics.
- The payer wallet is derived from token-balance ownership.
- One D1 batch updates the Payment Intent, invoice, customer wallet, receipt, audit record, and commerce outbox event.
- The outbox drains to merchant webhook deliveries with event-ID idempotency. Background reconciliation finds QR payments after checkout closes.
Refund Flow
Refunds are non-custodial. The server reserves the refundable amount and builds an unsigned SPL or Token-2022 transfer from the merchant settlement wallet to the verified original payer, including the exact VelaPay refund memo. The merchant wallet signs and broadcasts it.
The server verifies the refund transfer before one batch updates the Refund Intent, Payment Intent, invoice, refund receipt, credit note, audit log, and outbox. Queued, signing, broadcasting, and confirmed amounts reserve the balance; failed and cancelled refunds release it.
Security Invariants
- Only
publicPayment Intents execute. Pending private modes fail withprivacy_mode_not_available. - Cluster, mint, token program, decimals, recipient, and settlement ownership are server snapshots.
- A signature cannot confirm two payments or refunds.
- Invoice-backed callers cannot override invoice economics or identity.
- Active invoice intents and transaction signatures are unique at the database layer.
- Refund reservations and database triggers prevent concurrent over-refunds.
- Merchant API keys are hashed, scoped, revocable, and server-only.
- Redirects fail closed without an allowlist.
- Domain verification requires an expiring DNS TXT challenge; wallet verification requires SIWS proof.
- Every customer and wallet link is merchant-scoped.
- Auditors can read commerce data and exports but every mutation returns
403.
Data and Event Consistency
D1 has no interactive transactions, so related writes use ordered batch() statements plus constraints and triggers. The commerce event outbox is written in the same batch as the business state. Consumers deduplicate using the UUID event ID, not the transaction signature.
The public schema and subscription set is:
payment_intent.createdpayment_intent.confirmedpayment_intent.expiredrefund.createdrefund.confirmedrefund.failed
The accepted v1.9 devnet producer transactionally enqueues payment_intent.confirmed and refund.confirmed. The other four contracts are available in the SDK/webhook schemas and subscription UI but do not yet have dashboard producer call sites. Documentation and integrations must not treat them as active deliveries until that gap is closed.
Operational Limits
The accepted v1.9 deployment is devnet-only. C-SPL execution, private refunds, Terminal, Blinks, payouts, escrow, VelaPay Pages, and fresh one-time addresses are deferred. The durable rollout evidence lives in vela-dashboard/docs/runbooks/v1.9-devnet-rollout-report.md.