From bd00afee2467e03085d8b091473396a0aab0a829 Mon Sep 17 00:00:00 2001 From: obchain Date: Mon, 22 Jun 2026 13:19:47 +0530 Subject: [PATCH 1/4] docs(readme): reflect live deploy, on-chain perp, and shipped pipeline The README still described VolX as an M1-in-progress, read-only research project with no on-chain components. That no longer matches reality: the full pipeline, public API, on-chain Sepolia perp, and CI/CD deploy are all live. - Project status: M1 done, M2 in progress (multi-venue + perp + deploy shipped); roadmap checkmarks updated to match. - API section: 'planned' -> live, real base URL (volx-api.ancilar.com), example payload matches the actual response shape. - Security: drop the false 'no on-chain components / no wallet code' claim; document the testnet contract + keeper-key surface and the Cloudflare Tunnel exposure model. - Tech stack deploy row + 'exchange-neutral' bullet: match the shipped self-hosted + Netlify + Docker Hub setup and live multi-venue blend. - Fix the stale #api-planned anchor in the header nav and contents. --- README.md | 117 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index b0a8618..459889b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@

Methodology · Quickstart · - API · + API · Roadmap · Changelog

@@ -45,7 +45,7 @@ - [Tech stack](#tech-stack) - [Quickstart](#quickstart) - [Repo layout](#repo-layout) -- [API (planned)](#api-planned) +- [API](#api) - [Data sources](#data-sources) - [Performance targets](#performance-targets) - [Project status](#project-status) @@ -79,8 +79,8 @@ VolX is: - **Auditable.** Every published row carries a content-hash of the strip set that produced it (`strip_hash`), so any value can be reproduced from the raw tick archive. -- **Exchange-neutral.** Starts with Deribit (dominant BTC + ETH options - venue); multi-venue median blending lands in M2. +- **Exchange-neutral.** Multi-venue median blending across Deribit, OKX, + and Bybit (see [Multi-venue robustness](#multi-venue-robustness)). - **Self-hostable.** No paid data feeds, no API keys required to run the ingestion locally, no proprietary math. @@ -321,7 +321,7 @@ publish — well under the 60 s cadence, even at M2 multi-venue load. | Frontend | **Next.js 15** (app router) + React 19 + Tailwind 4 + `lightweight-charts` | static-friendly, deterministic chart rendering | | Research | Python 3.14 + numpy + pandas + scipy + matplotlib + jupyter | the methodology was validated here before any Rust was written | | Lint policy | `unsafe_code = forbid`, clippy pedantic, `cargo fmt --check` | financial code; zero tolerance for memory bugs | -| Deploy (M3) | Oracle Cloud Always Free + Cloudflare + Vercel Hobby + GHCR | $0/mo recurring; ~$1/yr domain | +| Deploy | Self-hosted always-on server (Docker Compose) + Cloudflare Tunnel + Netlify + Docker Hub | always-on backend behind Cloudflare; static frontend on Netlify; images on Docker Hub, CI pull-deploys | Determinism, free-tier compatibility, and operational simplicity are the three non-negotiables. @@ -477,9 +477,11 @@ volx/ --- -## API (planned) +## API -The Go API is M1 scope. Endpoints below are the planned public shape. +The Go API is **live**. Public base URL: +[`https://volx-api.ancilar.com`](https://volx-api.ancilar.com/v1/index/bvol/latest) +(served from the always-on server, exposed via a Cloudflare Tunnel). ### REST @@ -493,23 +495,24 @@ GET /v1/options/strip ?venue=deribit&asset=BTC&expiry=2026-06-30 Example: ```bash -curl https://api.volx.dev/v1/index/BVOL/latest +curl https://volx-api.ancilar.com/v1/index/bvol/latest ``` ```json { - "index_id": "BVOL", - "value": 65.42, - "confidence": 0.97, - "strip_hash": "9c7a…", - "ts": "2026-05-25T12:00:00Z" + "index": "BVOL", + "value": 39.15, + "confidence": 0.19, + "source_strip_hash": "0x7b70e7a9…", + "ts": "2026-06-17T14:27:39Z", + "next_update_eta_seconds": 57 } ``` ### WebSocket ``` -wss://api.volx.dev/v1/stream +wss://volx-api.ancilar.com/v1/stream ``` Subscribe to one or more indices; receive `IndexValue` rows pushed on @@ -521,8 +524,8 @@ every 60-second publish. < {"type":"index","data":{"index_id":"EVOL","value":71.10,"ts":"..."}} ``` -Free tier: 60 req/min REST, 1 concurrent WS. M2 introduces auth-keyed -higher-tier limits. +Rate limit: 60 req/min REST, 1 concurrent WS. Auth-keyed higher-tier +limits land in M2. --- @@ -558,25 +561,32 @@ No paid feeds in v1. Multi-venue live in M2. ## Project status -VolX is in active development. +VolX is live on testnet. | Phase | Window | Deliverable | State | | --- | --- | --- | --- | | **M0** Research | Done | Python reference impl, validated math, DVOL gap diagnosed | **Complete** | -| **M1** Local pipeline | In progress | Rust ingest + engine → Go API → Next.js | Ingestion + reconnect shipped | -| **M2** Hardening | Pending M1 | Multi-venue, API keys, rate limit, status page, backups | Not started | -| **M3** Public launch | Pending M2 | Methodology page, aggregator listings, public dashboard | Not started | +| **M1** Local pipeline | Done | Rust ingest + engine → Go API → Next.js | **Complete** — full pipeline shipped, e2e smoke green | +| **M2** Hardening | In progress | Multi-venue, on-chain perp, live deploy, CI/CD | Multi-venue + on-chain perp + always-on deploy shipped; API keys / status page pending | +| **M3** Public launch | Pending M2 | Methodology page, aggregator listings, public dashboard | Methodology + dashboard live; aggregator listings pending | ### What works today -- **`volx-ingestion`** — live Deribit WebSocket connector with REST - instrument discovery, batched subscribe, ticker → `OptionTick` - normalisation, reconnect + exponential backoff (1 → 2 → 4 → 8 → 16 s, - cap 30 s, ±20 % jitter), per-venue task isolation. -- **`volx-shared-types`** — `OptionTick`, `Strip`, `StripQuote`, - `IndexValue`, `StripHash`, `Years`, `Minutes` and the venue/asset/kind - enums. All serde-round-trip-tested; domain invariants enforced at - deserialize time. +- **Full off-chain pipeline, live** — `volx-ingestion` (multi-venue + Deribit/OKX/Bybit WS connectors, reconnect + backoff, per-venue + isolation) → `volx-normalizer` (staleness/spread/intrinsic filters + + ClickHouse persistence) → `volx-engine` (per-venue strip, Carr-Madan + variance integral, 30-day interpolation, median blend, outlier drop, + confidence score) → Go/Fiber API (REST `/v1/{latest,history,options/strip}` + + WS `/v1/stream`) → Next.js dashboard. +- **Live public API + frontend** — backend at + [`volx-api.ancilar.com`](https://volx-api.ancilar.com/v1/index/bvol/latest) + (always-on server behind a Cloudflare Tunnel), frontend at + [`volx-frontend-29824.netlify.app`](https://volx-frontend-29824.netlify.app). +- **On-chain perp on Sepolia** — VolXOracle + VolXPerpV2 + keeper + + `/trade` `/pool` `/dashboard` wallet app. See the on-chain section above. +- **CI/CD** — GitHub Actions builds + pushes images to Docker Hub, then + pull-deploys to the server over a Cloudflare-Access SSH tunnel. - **Python reference impl** — fitted-IV variant adopted as canonical; matches DVOL within 5.83 % median absolute relative error (the +5.77 % bias is a structural inverse-contract artefact, not a math error — see @@ -584,12 +594,10 @@ VolX is in active development. ### What's next -- `normalizer` filters (#12) + ClickHouse writer (#15, #16) -- `engine` strip builder (#17), variance integral (#18), 30-day interp - (#19), scheduler (#20) -- Go API skeleton (#22) → endpoints (#23) → WebSocket stream (#24) -- Next.js scaffold (#25) → landing (#26) → live chart (#27) -- CI (#28) +- API keys + auth-keyed rate-limit tiers (M2) +- Public status page + backup/restore runbook (M2) +- Aggregator submissions + public launch (M3) +- Contract audit before any non-testnet use --- @@ -648,19 +656,20 @@ High-level landmarks: ``` M0 ✓ Research + math reference + DVOL diagnosis -M1 Local live pipeline +M1 ✓ Local live pipeline ├── Rust workspace skeleton (#7) ✓ ├── shared-types (#8) ✓ ├── Ingestion: Deribit WS (#9) ✓ - ├── Reconnect + backoff (#10) ▶ (this milestone) - ├── Tracing + Prometheus (#11) - ├── Normalizer filters + ClickHouse (#12-16) - ├── Engine: strip / variance / interp / cron (#17-20) - ├── Engine numerical acceptance (#21) - ├── Go API: REST + WS (#22-24) - └── Next.js dashboard (#25-27) -M2 Multi-venue, API keys, status page, backups, SLO monitoring -M3 Methodology page, aggregator submissions, public launch + ├── Reconnect + backoff (#10) ✓ + ├── Tracing + Prometheus (#11) ✓ + ├── Normalizer filters + ClickHouse (#12-16) ✓ + ├── Engine: strip / variance / interp / cron (#17-20) ✓ + ├── Engine numerical acceptance (#21) ✓ + ├── Go API: REST + WS (#22-24) ✓ + └── Next.js dashboard (#25-27) ✓ +M2 ▶ Multi-venue ✓ · on-chain perp ✓ · always-on deploy + CI/CD ✓ + └── API keys, status page, backups, SLO monitoring +M3 Methodology page ✓ · public dashboard ✓ · aggregator submissions ``` --- @@ -712,15 +721,25 @@ notebooks within `1e-6` in `σ²_30d` to ship. ## Security -VolX is read-only software at v1: no on-chain components, no wallet code, -no user funds custody, no auth-token issuance. The threat surface is: - +The off-chain index pipeline is read-only software (no user funds custody, +no auth-token issuance). The on-chain perp adds a smart-contract surface, +**deployed to Ethereum Sepolia testnet only — not audited, demo liquidity, +no real funds.** The threat surface is: + +- **On-chain contracts** (testnet). `unsafe`-free off-chain code; + contracts are `VolXOracle` + `VolXPerpV2` + `MockUSDC` on Sepolia. + **Not audited — do not deploy to mainnet or fund with real assets.** + See [`docs/onchain-demo.md`](./docs/onchain-demo.md) for addresses. +- **Keeper key** — the oracle/order signer is a testnet key, held in + GitHub Actions secrets / the server `.env` (mode 0600), never in the + repo. Compromise affects testnet funds only. - **Ingestion auth keys** (M2 onwards, for `.raw` channels). Stored in Keychain / Vault / k8s secrets, never in env files or repo. - **API key issuance** (M2). Hashed at rest; rate-limited and per-key audit logged. -- **Public dashboard** (M3). Cloudflare WAF + Caddy TLS; no PII - collected. +- **Public dashboard** — backend behind a Cloudflare Tunnel (TLS, + no inbound ports open on the server); frontend static on Netlify; no + PII collected. To report a vulnerability privately: open a security advisory on GitHub (`obchain/volx` → Security → Report a vulnerability) rather than a public From f170dfe87f6b25355bb0e60af34e71a39480aefb Mon Sep 17 00:00:00 2001 From: obchain Date: Mon, 22 Jun 2026 13:25:02 +0530 Subject: [PATCH 2/4] docs(readme): correct WebSocket frame example to live wire shape The WS example carried the old planned shape. Match the actual ClientTick emitted by api/internal/stream/hub.go: no 'data' wrapper, 'channel' (not 'index_id'), 'type':'tick', and 'ts' as Unix epoch milliseconds. Subscribe channels are lower-case index ids. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 459889b..ec17f0e 100644 --- a/README.md +++ b/README.md @@ -515,13 +515,14 @@ curl https://volx-api.ancilar.com/v1/index/bvol/latest wss://volx-api.ancilar.com/v1/stream ``` -Subscribe to one or more indices; receive `IndexValue` rows pushed on -every 60-second publish. +Subscribe to one or more channels (lower-case index ids); receive a `tick` +frame per channel on every 60-second publish. `ts` is Unix epoch +milliseconds. ```json -> {"action":"subscribe","channels":["BVOL","EVOL"]} -< {"type":"index","data":{"index_id":"BVOL","value":65.42,"ts":"..."}} -< {"type":"index","data":{"index_id":"EVOL","value":71.10,"ts":"..."}} +> {"action":"subscribe","channels":["bvol","evol"]} +< {"type":"tick","channel":"bvol","value":39.15,"ts":1718634459188,"confidence":0.19} +< {"type":"tick","channel":"evol","value":58.57,"ts":1718634459188,"confidence":0.19} ``` Rate limit: 60 req/min REST, 1 concurrent WS. Auth-keyed higher-tier From a3f1683c2a1082b895cb4425f3c57013943c7ea3 Mon Sep 17 00:00:00 2001 From: obchain Date: Mon, 22 Jun 2026 14:28:37 +0530 Subject: [PATCH 3/4] docs(readme): mark M2 (multi-venue) and on-chain perp as complete The Phase 2 milestone (OKX + Bybit connectors, per-venue strip + median blend, outlier drop, confidence score, per-service Dockerfiles) is fully shipped and the milestone is closed, as is the on-chain perp milestone. The previous status table conflated M2 with later, unscoped hardening work (API keys, status page, backups) and so read 'in progress'. - Status table: M2 + on-chain perp + deploy/CI-CD marked Complete; M3 in progress (methodology + dashboard live, aggregator listings pending). - Roadmap: M2 checked off; unbuilt hardening moved to a 'Future' line. - Moved API keys / rate-limit tiers / status page / backups out of M2 and into clearly-future work across the API, security, and perf sections. --- README.md | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index ec17f0e..da57b44 100644 --- a/README.md +++ b/README.md @@ -526,7 +526,7 @@ milliseconds. ``` Rate limit: 60 req/min REST, 1 concurrent WS. Auth-keyed higher-tier -limits land in M2. +limits are future work (not yet scoped). --- @@ -542,7 +542,7 @@ limits land in M2. | Published VIX (CBOE benchmark) | CBOE daily close CSV | $0 | daily | | Risk-free rate `r` | constant 0 (matches DVOL; see METHODOLOGY §4.4) | n/a | n/a | -No paid feeds in v1. Multi-venue live in M2. +No paid feeds in v1. Multi-venue (Deribit + OKX + Bybit) is live. --- @@ -555,8 +555,8 @@ No paid feeds in v1. Multi-venue live in M2. | Engine determinism | bit-for-bit identical across runs | M1 #21 (`cargo test`) | | Engine vs Python reference | `|Δσ²_30d| < 1e-6` | M1 #21 acceptance gate | | Public API p95 latency (REST `latest`) | < 50 ms | M1 #22-24 | -| Public WS broadcast fan-out | 100 concurrent subs / instance | M2 sizing | -| Index publish miss rate | < 0.1 % of expected 60s slots | M2 SLO | +| Public WS broadcast fan-out | 100 concurrent subs / instance | future sizing | +| Index publish miss rate | < 0.1 % of expected 60s slots | future SLO | --- @@ -568,8 +568,10 @@ VolX is live on testnet. | --- | --- | --- | --- | | **M0** Research | Done | Python reference impl, validated math, DVOL gap diagnosed | **Complete** | | **M1** Local pipeline | Done | Rust ingest + engine → Go API → Next.js | **Complete** — full pipeline shipped, e2e smoke green | -| **M2** Hardening | In progress | Multi-venue, on-chain perp, live deploy, CI/CD | Multi-venue + on-chain perp + always-on deploy shipped; API keys / status page pending | -| **M3** Public launch | Pending M2 | Methodology page, aggregator listings, public dashboard | Methodology + dashboard live; aggregator listings pending | +| **M2** Multi-venue & index quality | Done | OKX + Bybit connectors, per-venue strip + median blend, outlier drop, confidence score, per-service Docker | **Complete** — all 6 issues closed | +| **On-chain perp** (testnet) | Done | VolXOracle + VolXPerpV2 + keeper + `/trade` `/pool` `/dashboard` wallet app on Sepolia | **Complete** — all 11 issues closed; live demo | +| **Deploy & CI/CD** | Done | Always-on server (Docker Compose), Cloudflare Tunnel, Netlify, Docker Hub, GitHub Actions pull-deploy | **Complete** — live | +| **M3** Public launch | In progress | Methodology page, public dashboard, aggregator listings | Methodology + dashboard live; aggregator submissions pending | ### What works today @@ -595,11 +597,12 @@ VolX is live on testnet. ### What's next -- API keys + auth-keyed rate-limit tiers (M2) -- Public status page + backup/restore runbook (M2) - Aggregator submissions + public launch (M3) - Contract audit before any non-testnet use +Future (not yet scoped): API keys + auth-keyed rate-limit tiers, public +status page, backup/restore runbook, SLO monitoring. + --- ## On-chain perp (live on Sepolia testnet) @@ -668,9 +671,11 @@ M1 ✓ Local live pipeline ├── Engine numerical acceptance (#21) ✓ ├── Go API: REST + WS (#22-24) ✓ └── Next.js dashboard (#25-27) ✓ -M2 ▶ Multi-venue ✓ · on-chain perp ✓ · always-on deploy + CI/CD ✓ - └── API keys, status page, backups, SLO monitoring -M3 Methodology page ✓ · public dashboard ✓ · aggregator submissions +M2 ✓ Multi-venue & index quality (OKX + Bybit, median blend, outlier drop, confidence) +On-chain perp ✓ VolXOracle + VolXPerpV2 + keeper + wallet app (Sepolia) +Deploy + CI/CD ✓ always-on server, Cloudflare Tunnel, Netlify, Docker Hub +M3 ▶ Methodology page ✓ · public dashboard ✓ · aggregator submissions +Future API keys · status page · backups · SLO monitoring (unscoped) ``` --- @@ -734,9 +739,9 @@ no real funds.** The threat surface is: - **Keeper key** — the oracle/order signer is a testnet key, held in GitHub Actions secrets / the server `.env` (mode 0600), never in the repo. Compromise affects testnet funds only. -- **Ingestion auth keys** (M2 onwards, for `.raw` channels). Stored in +- **Ingestion auth keys** (future, for `.raw` channels). Stored in Keychain / Vault / k8s secrets, never in env files or repo. -- **API key issuance** (M2). Hashed at rest; rate-limited and per-key +- **API key issuance** (future). Hashed at rest; rate-limited and per-key audit logged. - **Public dashboard** — backend behind a Cloudflare Tunnel (TLS, no inbound ports open on the server); frontend static on Netlify; no From 57a9792218dbafb73105daa0012c8e584ce4ab8a Mon Sep 17 00:00:00 2001 From: obchain Date: Mon, 22 Jun 2026 14:36:59 +0530 Subject: [PATCH 4/4] docs(readme): mark M3 complete; drop out-of-scope analytics + aggregator listings Public launch is shipped: methodology page, public dashboard, and the live backend + frontend deploy are all up. External aggregator/directory submissions and product analytics were never project goals, so they are removed from the roadmap rather than tracked as pending. - Status table + roadmap: M3 -> Complete. - Remove 'aggregator submissions' from What's next. - Retag stale 'Oracle Cloud (M3)' repo-layout comments to the actual self-hosted + Cloudflare deploy. --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index da57b44..4dbd785 100644 --- a/README.md +++ b/README.md @@ -463,10 +463,10 @@ volx/ │ ├── docker/ │ ├── docker-compose.yml # local dev: ClickHouse + Redis -│ └── docker-compose.prod.yml # Oracle Cloud (M3) +│ └── docker-compose.prod.yml # full prod stack (self-hosted server) │ -├── deploy/ # M3 -│ ├── oracle-cloud-init.sh +├── deploy/ # deploy assets +│ ├── oracle-cloud-init.sh # legacy cloud-init (unused; current deploy is server + Cloudflare) │ └── grafana-dashboards/ │ └── docs/ @@ -571,7 +571,7 @@ VolX is live on testnet. | **M2** Multi-venue & index quality | Done | OKX + Bybit connectors, per-venue strip + median blend, outlier drop, confidence score, per-service Docker | **Complete** — all 6 issues closed | | **On-chain perp** (testnet) | Done | VolXOracle + VolXPerpV2 + keeper + `/trade` `/pool` `/dashboard` wallet app on Sepolia | **Complete** — all 11 issues closed; live demo | | **Deploy & CI/CD** | Done | Always-on server (Docker Compose), Cloudflare Tunnel, Netlify, Docker Hub, GitHub Actions pull-deploy | **Complete** — live | -| **M3** Public launch | In progress | Methodology page, public dashboard, aggregator listings | Methodology + dashboard live; aggregator submissions pending | +| **M3** Public launch | Done | Methodology page, public dashboard, live public deploy | **Complete** — methodology + dashboard live; backend + frontend deployed | ### What works today @@ -597,7 +597,6 @@ VolX is live on testnet. ### What's next -- Aggregator submissions + public launch (M3) - Contract audit before any non-testnet use Future (not yet scoped): API keys + auth-keyed rate-limit tiers, public @@ -674,7 +673,7 @@ M1 ✓ Local live pipeline M2 ✓ Multi-venue & index quality (OKX + Bybit, median blend, outlier drop, confidence) On-chain perp ✓ VolXOracle + VolXPerpV2 + keeper + wallet app (Sepolia) Deploy + CI/CD ✓ always-on server, Cloudflare Tunnel, Netlify, Docker Hub -M3 ▶ Methodology page ✓ · public dashboard ✓ · aggregator submissions +M3 ✓ Methodology page · public dashboard · live public deploy Future API keys · status page · backups · SLO monitoring (unscoped) ```