1. Cryptographic build identity (Layer A)
The Spring Boot api, Java worker, and Express site are all signed with
the same offline key before rollout. An Ed25519 signature over the
canonical manifest {service, commit, image_digest, builtAt}
is written into Cloud Run env vars and exposed via identity endpoints.
If someone swaps the image β the signature won't match. If someone
forges the manifest β it won't verify against the committed public key.
What this closes
- An attacker with Cloud Run or build-pipeline access who tries to push a malicious image β the Pulse probe catches the mismatch within an hour.
- A contractor with temporary deploy rights cannot later sign their own build in our name β they don't hold the key.
- "Someone swapped the bytes" stops being a guess and becomes arithmetic: either the signature is valid or it isn't.
2. Explicit risk gates before any LIVE order
Before a real order reaches the exchange, the request passes through a layered chain of
independent checks in strict order. Each gate has a unit test and throws
a structured ProductPolicyException with a specific
risk_code. PAPER mode has only 2 gates β symbol allowlist +
plan allows paper. LIVE passes the full chain.
-
Symbol allowlist
SYMBOL_NOT_ALLOWED
Symbol must be on the permitted list.
-
Regime guard
DANGEROUS
Market must not be in DANGEROUS regime (realised volatility + drawdown).
-
Runtime kill switch
quantor.trading.live.enabled
Global flag must be on.
-
User allowlist
quantor.trading.live.allowedUserIds
User ID must be in the runtime allowlist.
-
Non-zero notional
Cannot start LIVE on zero order size.
-
Active subscription
Subscription must be active and current.
-
Account not frozen
Account in good standing, bot count under plan limit.
-
Plan allows LIVE
The current plan permits LIVE β FREE does not. Starter allows LIVE on EMA only; advanced strategies (Breakout V1, TS Momentum V1, Adaptive Pro, Custom) require Pro or Teams.
-
LIVE_ADVANCED mode
advancedStrategies
Advanced mode requires a plan with the advanced-strategies feature.
-
Telegram linked
Telegram account must be linked β dual-channel control.
-
Strategy whitelist
Strategy must be in the permitted set for the execution mode.
-
Exchange keys verified
Exchange API keys must be verified live, not just entered.
-
Max-notional ladder
Per-plan cap on order notional:
Starter β€ $250
Pro β€ $5k
Teams β€ $25k
-
Daily-loss ladder
Per-plan daily-loss circuit breaker (source of truth: PlanLimitsCatalog.java):
Free β€ 1%
Starter β€ 2%
Pro β€ 5%
Teams β€ 10%
3. Regime detector β we're willing to sit on the bench
Quantor calculates the current market regime from realised volatility
and drawdown from peak. When the regime is DANGEROUS,
LIVE starts are blocked β regardless of plan, allowlist, or any other
permission. PAPER works in DANGEROUS: a hostile market is a great time
to test strategies on paper rather than on real money. The current
regime is open to everyone:
api/v1/market/regime.
The kind of contract this is
Most bots in this category optimise for volume β more trades, more
fees, more vendor revenue. We optimise for "don't lose the user's
money on a bad day." This reduces our own revenue during volatile
periods, and we consider that a conscious trade-off.
4. Self-custody β by construction, not by promise
Quantor doesn't hold your money. Ever. By design:
- You create the exchange API key yourself on the venue you pick in the dashboard. Required permissions: spot trading only, withdrawals disabled β keys with withdrawal permission are rejected during save and verification.
- The key is encrypted with an AES-GCM master key that lives in GCP Secret Manager β a separate trust boundary from the database.
- The database holds only the encrypted blob + last4 + a
verified=true/false flag.
- Even if Quantor's database leaks β keys can't be decrypted without the master key. And even if decrypted, funds can't be withdrawn β the exchange key forbids it.
5. Tamper-evident audit chain (Layer B)
Every audit-relevant event is written with a hash that depends on
the previous one: hash = sha256(prev_hash + canonical_payload).
Any attempt to silently modify or delete a record after the fact
breaks the chain β subsequent hashes stop matching. A verifier
endpoint reproduces the head hash independently; the Pulse probe
obs.audit-chain checks integrity every hour.
Threat model
The scenario "a future intruder with database access quietly deletes
a bad trade and pretends it never happened" β caught arithmetically.
The scenario "a future founder edits history to suit themselves" β
same. The chain cannot be forged without holding every key and every
hash.
6. Pulse β one-click synthetic probe
13 probes through every layer of the stack in ~10 seconds. Side-effect
free β writes nothing, sends no messages to real users, buys nothing.
If anything turns red, the row shows the exact file:method:line where
the chain broke. It isn't a "notification" β it's a real synthetic
test scenario the operator runs after every deploy.
What it checks
| Probe | What it verifies |
| health | API is alive |
| db.read | SELECT 1 round-trip via JPA |
| db.write | insert + delete on pulse_runs |
| plan.catalog | 3 paid plans, limits match the source code |
| strategy.catalog | 6 strategies registered |
| market.regime | regime detector returns a valid MarketRegime |
| worker.heartbeat | worker wrote a heartbeat β€ 60s ago |
| pipeline.dry-run | EMA strategy processes 100 synthetic candles |
| billing.lemonsqueezy | LS checkout URLs are valid |
| billing.cryptocloud | HMAC self-test (matching + tampered) |
| audit-chain.head | hash chain reproduces correctly |
| sentry | DSN is configured |
| build.signature | Ed25519 signature verifies against the committed public key |
Compared to a typical crypto-bot SaaS
Open numbers from public pricing pages as of June 2026. Not an attack
on competitors β just facts.
|
Typical bot SaaS |
Quantor |
| Build signature |
none β unverifiable |
Ed25519, public key |
| Risk policy |
usually one β a stop-loss |
14 gates + regime guard |
| Custody |
sometimes opaque |
API keys, withdraw disabled |
| Audit chain |
plain log (deletable) |
hash chain (delete = break it) |
| Entry price |
$25β30/mo |
$19/mo |
| Telegram-native control |
notifications only |
bot commands + Mini-App |