SoW: Merge aiex-main into main

Baseline: origin/main...origin/aiex-main as of 2026-07-02 — 292 unique commits on aiex-main, 324 files, +52,474/−2,957. Trial merge (git merge-tree) is conflict-free; aiex-main contains main up to 2026-07-01.

Fifteen PRs. Every slice is produced mechanically from the known-good aiex-main tree: branch off main, git restore --source=origin/aiex-main -- <paths>, regenerate Cargo.lock, PR. Workspace Cargo.toml entries land with the slice that needs them (wiremock → PR 4, zip → PR 11, ax-risk-engine2 alias → PR 6, ax-risk alias → PR 8, member entries as each new crate lands). Convergence check after each merge: git diff --stat origin/main...origin/aiex-main shrinks monotonically to zero. Routine main → aiex-main syncs continue until PR 15 lands.

Ordering: 1 → 2 → 3 → 4 form the foundation chain; 5–9 fan out in parallel after 4; 10–12 integrate into shared services; 13 → 14 carry the GUI; 15 flips infra. Critical path: 1 → 2 → 3 → 4 → 6 → 10 → 13 → 14 → 15.

The three new crates (PRs 5–7, ~31k lines combined) are pure additions — they cannot regress the EP3 path and should be reviewed for quality, not regression. The regression surface is concentrated in PRs 3, 10, and 13.

PR 1 — DB schema

db/postgres/1.sql (+215, additive Bitnomial tables), db/postgres/a-3703-bitnomial-product-config.sql backfill, db/clickhouse/init.sql. +262. Declarative Atlas schema — additive only, but confirm before merge since just migrate-db applies it to main-deployed envs.

PR 2 — sdk-internal data layer

sdk-internal/db (entities +839, new btnl_account_index.rs), sdk-internal/clickhouse (bitnomial_fix, schema, open-interest tests), crypto/encrypted.rs, db/field_encryption.rs. +1.5k/−99. Needs PR 1.

PR 3 — sdk-internal core + public SDK

edition.rs, account_id.rs, constants.rs, new matching_engine.rs, protocol.rs (+531), redis keys/values, risk/buying_power_updater.rs, web/ip_rate_limiter.rs, test-batteries, rs/test-utils (new poll.rs), rs/health/types.rs; rs/sdk (docs-only: doc-comment rewording + STP behavior docs). +1.3k/−104. Review protocol.rs and redis_keys.rs hardest — existing services deserialize these. Verify the rs/sdk doc changes leak nothing internal.

PR 4 — bitnomial library + btp-mock

rs/bitnomial: FIX seqnum-reset epochs, drop-copy keying by reset epoch, clearing API client (clearing/), REST fills, account_map.rs, BTP order ids, consumer subscriber; rs/btp-mock server updates. Adds wiremock workspace dep. +4.6k/−485. Needs PR 3. Unblocks all of Phase 2.

PR 5 — md-btp (new crate)

Market-data service: BTP catalog/connection manager, order book, candle minting/clock, staleness + ticker publishing, stats poller; plus the marketdata-publisher/main.rs one-liner. Workspace member + aiex-marketdata-publisher alias (leaf — no other consumer). +9.1k.

PR 6 — bitnomial-order-gateway (new crate)

Full OG: FIX/BTP venue sessions, reconciler, order state/tracker/ops, margin (check/open-orders/publish), cancel-on-disconnect, per-IP rate limiting, REST/WS services, proptests, wire snapshots. Needs ax-risk-engine2 workspace alias. +16.3k. Largest slice; acceptable as one PR because purely additive and already soaking on aiex-main — reference originating PRs (#2785, #2796–2798, #2615) in the description. Sub-split if review stalls: venue transport / order state + margin / REST + WS + tests.

PR 7 — trade-engine-bn (new crate)

Fills state machine (+ proptests), backfill, positions, accounts monitor, FIX consumer client, translate layer. +5.8k.

PR 8 — risk engines

risk-engine-bitnomial: cold-start bootstrap (bootstrap.rs, rest_bootstrap.rs), fix_dropcopy_task.rs, marks_task.rs, calculator/ data_monitor updates; risk-engine: data_monitor, ax-risk moved to workspace alias. +2.9k/−455. Needs PR 4.

PR 9 — recon-engine + index-publisher

recon-engine/runtime.rs (matching-engine runtime), index-publisher bitnomial source + pyth streamer/health, transaction-engine test touch. +0.7k. Needs PR 4.

PR 10 — api-gateway + ep3 + order-gateway (regression hotspot)

Venue-mapping dedicated column [A-3703], Bitnomial matching-engine + market- data cache [A-3684], auth/auth_routes, ep3/instrument_manager + instrument_spec, order-gateway auth/rest/ws edits, openapi json. +1.3k/−533. Needs PR 3 (and PR 5 only if the MD cache imports md-btp types — verify when cutting). This is the one Rust slice that modifies the live EP3 path: budget the most review here and exercise the CLAUDE.md lifecycle matrix (client disconnect, server-initiated disconnect, restart/crash, reconnect/recovery) before rollout.

PR 11 — onboarding-gateway

US individual/institutional onboarding backend, Box export (box_client.rs, export.rs; zip + csv deps, reqwest multipart), KYC, validation, admin routes. +3.4k/−208. Needs PR 3.

PR 12 — admin-cli

Attributed-open / fills / md-btp-observe probes, instruments seeding, bitnomial_instruments.yaml, ax-bitnomial dep. +1.6k. Needs PR 4.

PR 13 — GUI shared (gui/packages)

New edition.ts / branding.ts / useEdition / useOnboardingLock / timeInForce utils (+tests); edition-aware resting TIF [A-3925], band-aware market-order preview [A-3818], order form/submit, orders table, close- position flow, california OrderPanel. +2.4k/−358. Needs PR 10 for API surface. Touches the live trade flow for existing users — the edition gating is exactly what to review: EP3-edition behavior must be a no-op.

PR 14 — GUI apps (gui/apps)

web: onboarding flow pages, aiex signup routing, ToS gate, legal PDFs, account/trade page edits; admin: edition.ts, sidebar, login. +1.0k/−507. Needs PRs 11 and 13.

PR 15 — infra flip

aiex gold/GUI workflows, Dockerfile.gold-aiex (must include onboarding-gateway per #2641 follow-up), compose.yml, configs/ (aiex_demo_gui, dev_local), justfile, deny.toml, residual workspace Cargo.toml/Cargo.lock. +0.3k. Last; after it, git diff origin/main origin/aiex-main must be empty and aiex-main can be retired.

Rollout gates