Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rivermarkets.com/llms.txt

Use this file to discover all available pages before exploring further.

This page summarizes how River Markets is designed so that even in worst-case scenarios, the blast radius stays small.

API key signing (Ed25519)

API authentication is asymmetric. When you create an API key, the server generates an Ed25519 keypair, stores the public key, and returns the private key to you exactly once. We picked Ed25519 over the alternatives because it signs roughly 30× faster than RSA, has small (32-byte) keys, signs deterministically (no random number generator required at signing time, which removes a whole class of implementation bugs), and is hardened against timing and side-channel attacks.
  • The private key never traverses the wire after creation. Every request is signed locally; the server only ever verifies the signature.
  • A full database compromise cannot forge requests. An attacker with read access to our DB sees public keys, which doesn’t enable to sign orders.
  • Replay protection. Ed25519 signatures are deterministic — the same request always produces the same signature — so the signature alone is not replay-proof. We dedupe each signature in Redis with a 60-second TTL: a captured request cannot be resubmitted, even within the clock-skew window.
  • Rotation is in-place. Rotating a key swaps the underlying material but keeps the key_id stable : you only update one secret, not your config.
See Authentication for the protocol details.

Row-Level Security (RLS)

Every table in our database has Row-Level Security policies that scope queries to the authenticated user. RLS is enforced at the database layer, not in application code : so even if a code path forgets to filter by user_id, the DB refuses to return rows that don’t belong to the caller.
  • Each request runs as a authenticated role, never as a superuser.
  • Subaccounts, orders, fills, positions, balances, credentials, withdrawals, all gated by the same identity primitive.
The practical effect: there is no API path, supported or otherwise, that can return another user’s data.

Exchange credentials

When you add Polymarket or Kalshi credentials to a subaccount, they are encrypted with asymmetric encryption before being stored. The decryption key lives only in the trading service that needs them at execution time, they are never in plaintext at rest, never logged, never returned by any API endpoint.
  • Credentials are bound to the subaccount they were added to.
  • Deleting a subaccount deletes its credentials. No archival, no soft delete.
  • Credentials are rotated by replacing them; the old version is overwritten, not retained.

Transport

All traffic, REST, WebSocket, and database connections , runs over TLS. The API and the database are not reachable on the public internet without TLS termination.

Database hardening

Beyond RLS, the database instance is locked down at the platform level:
  • Dangerous procedural languages (plpython3u, plperlu, plsh) are removed and revoked at install time, no path to OS-level execution from a SQL injection, even if one existed.
  • Function creation is audited via DDL event triggers.
  • The service-account role used by the API has BYPASSRLS revoked, so it cannot accidentally read across users.

What this means for you

  • Treat your API private key like a password: store it in an env var or secret manager, never in source control.
  • Rotate keys if you suspect exposure, rotation is instant and atomic.
  • Exchange credentials added via the dashboard are safer than committing them to your own configuration, since we encrypt them and never let them out of the trading service.