---
title: Design Log
description: Every decision in this design, dated, with reasoning — so it can be revisited and confirmed.
---

This is the record Jason asked for: what was decided, when, and why. The docs on this site are the source of truth for the API update; this page is the source of truth for _how they got this way_. Append-only — reversals get a new entry, not an edit.

## 2026-07-28 — Initial design

**D1. Docs-first development.** These docs are written **ahead of implementation** and act as the spec. The API is built to match the docs, not the other way around. Rationale: the current 5,240-line hand-written OpenAPI file proved that spec-after-code drifts; spec-before-code also gives Jason a reviewable artifact before any backend work is spent.

**D2. Two pillars + auth plane.** `/context` (market data engine) and `/runtime` (execution), with `/account` for keys. Rationale: matches the business ("infrastructure AI agents build on") and replaces version-prefixes-as-product-matrix. Framework and venue become request fields — adding either never mints a new API version.

**D3. Endpoint budget ~30, down from ~138.** Consolidations: status/result embedded in resource GETs; paper trading as `mode`, not a resource tree; one deployment create for all frameworks. The original draft used one `PATCH` verb for lifecycle; D34 supersedes that with explicit lifecycle endpoints after review found the loose body too ambiguous.

**D4. BYOK-only draft superseded.** The original draft removed custody endpoints from the public surface and treated the API as BYOK-only. D33 and D35 supersede it: managed trading wallets are the default account path, BYOK remains the self-custody option, and wallet operations live under `/wallet` with explicit idempotency and polling contracts.

**D5. OTP returns the key in-band.** Replaces the magic-link flow that emailed the plaintext key. Rationale: an agent can't read its operator's inbox; a six-digit code is human-relayable and expires in 10 minutes; a key in an inbox is a standing liability. Existing abuse controls (3/6h rate limit, disposable-domain screening) carry over unchanged.

**D6. Scoped-key preference became a hard default.** The original draft labeled `scoped_key: false` with a warning rather than rejecting master keys. D33 supersedes it: unrestricted credentials are rejected unless the request body includes explicit unsafe-credential acknowledgements. Rationale: agent-facing APIs need unsafe choices to be machine-visible and deliberate, not hidden behind a 2xx.

**D7. Client-side onboarding ceremony (`@superior-trade/onboard`).** Agent-wallet approval and builder-fee signatures move to an open-source CLI run locally, because only the user's master key can sign them and BYOK forbids us receiving it. The API checks readiness; it never signs.

**D8. Datasets get an HTTP surface.** `/context/candles` + `/context/funding` serve the existing GCS releases (Lighter: 1m OHLCV + mark + hourly funding, ~226 markets; Polymarket: outcome history). Rationale: the data engine already exists and is validated — it was simply unexposed. Immutable `release` IDs make reads reproducible and CDN-cacheable.

**D9. Honest-data invariants.** Venue-side history holes are served as `gaps`, never interpolated. Backtest results always include `market_change_pct`. Paper metrics carry `simulated: true`. Rationale: these are brand values (see the leaderboard's mandatory disclaimer today) promoted to API contract.

**D10. Spec generated from code when built.** Zod schemas → OpenAPI via `@hono/zod-openapi` (already a dependency, currently unused). The hand-written spec file is retired. These MD pages remain the narrative layer; the generated spec becomes the reference layer.

**D11. Agent-native docs serving.** At this point, every page was fetchable as raw markdown at `/md/<path>`; `/llms.txt` was generated from the nav tree; error responses carried `docs_url`. Superseded by D41's canonical `/<path>.md` URLs. Modeled on vercel.com/docs, which serves markdown+frontmatter to machine readers — verified live 2026-07-28.

**D12. Docs layout = Vercel, skin = terminal v2.** Three-column shell (sidebar / article / on-this-page), ⌘K search, card landing. Styling imports terminal-v2's actual tokens: lime `#a3e635` on near-black, DM Sans + Space Mono, liquid-glass panels. Dark-only in this preview; the terminal's GitHub-Light remap is planned, logged here so it isn't forgotten.

**D13. Error taxonomy commitments.** Stable append-only codes; distinct problems get distinct codes (`credentials_missing` ≠ `account_not_funded` — a direct lesson from the current API rewriting "not onboarded" as "not funded"); `docs_url` in every error.

**D14. Old API sunsets slowly.** v1/v2/v3 keep working during build-out; deprecation with `Sunset` headers and dates; `410` + `docs_url` at the end. Existing `st_live_` keys valid on both surfaces throughout.

## 2026-07-28 — Layout rebuilt against the measured Vercel docs system

**D15. The first pass looked nothing like Vercel's docs (Jason's call — correct), because it
was built from memory.** Rebuilt after pulling vercel.com/docs HTML + CSS chunks and
extracting the actual system: 64px sticky header (transparent over black, hairline on
scroll); 1400px page grid with 300px sidebar / fluid article / 240px sticky TOC; **search
box at the top of the sidebar** (not the header) with a ⌘K kbd; sidebar groups with 13px
gray labels and 14px-medium h-8 items at 1px gaps; H1 48/56 semibold at −6% tracking;
16/24 body `#a0a0a0` on black with `#ededed` headings; hairline borders at white/14%;
13/20 code in bordered rounded blocks with a 40px header row; breadcrumb + "Copy page"
utility row above the H1; TOC with "Was this helpful?" pill and scroll-to-top; **the docs
landing rendered inside the docs shell** (Vercel's index is a docs page with card grids,
not a marketing hero). All glass/glow surfaces dropped except the ⌘K modal — Vercel's
docs are flat; Superior identity is carried by the lime accent (links, active nav, badges),
DM Sans/Space Mono, and the black background, which happens to match Vercel's dark theme
exactly. Measured values are annotated in `app/globals.css`.

## 2026-07-28 — Header unified with the terminal (Jason-directed)

**D16. The docs header is the terminal's header.** Rebuilt to mirror
`terminal-v2/components/terminal/header.tsx`: 56px bar, `border-b white/10` over
`bg-black/40`, the v3 logo mark + "Superior Trade" wordmark (muted "Docs" suffix), and a
single **Open Terminal** CTA in the terminal's deposit-pill style (lime, rounded-full,
mono 10px bold uppercase). Removed per Jason: the "Design preview" badge and the separate
Terminal / superior.trade buttons. Rationale: the docs and the product should read as one
surface; the chrome users already know is the chrome the docs should wear.

## 2026-07-28 — Dual-eval validation round and the honesty pass it forced

Jason reset validation with a sharper rubric: (1) does the writing work for its actual
readers, (2) will the documented features work in practice. Two independent evaluators ran —
a reader-experience eval (four personas walking the docs end to end) and a feasibility eval
(every documented behavior graded EXISTS / BUILDABLE / HARD / FICTION against the real
`apps/api` backend). Feasibility bottom line: ~60% of the surface is a facade over machinery
that already runs; four load-bearing gaps (Nautilus paper mode, Nautilus per-deployment
metrics, HL/Binance dataset releases, delete guarantees on shared runtimes); two claims that
were flatly false. Fixes below — docs changed to be honest, not promises added.

**D17. The quickstart must be literally executable.** Rewrote it: paper deployment now
started explicitly (creation never starts — the docs said so and the quickstart forgot);
"flip to live" removed (mode is fixed at creation; live = new deployment); a complete
30-line runnable strategy included; `content-type` on every request; retitled plain
"Quickstart" (the "for Agents" title repelled the human half of the audience).

**D18. The human↔agent seam is documented, not implied.** The two deliberate human handoffs
(OTP; scoped-key after the local signing ceremony) are named as such, and the deployment
`GET` gained a `venue_account` readiness probe (`funded`, `balance_usd`) so an agent checks
funding instead of starting-and-hoping. Feasibility: the underlying balance checks exist.

**D19. Deletion honesty.** "After a 200 no process holding your key exists" was structurally
untrue for Nautilus shared runtimes (reconciler-based teardown; per-wallet shared
credential). New contract: `DELETE` → `202` + `deleting` status; `deleted` only after
confirmed teardown + credential destruction; shared-wallet credentials destroyed with their
last deployment. Confirmed-not-assumed is the strongest claim the architecture supports.

**D20. Network-restriction claim retracted.** The docs claimed sandbox egress restricted to
the venue with violations failing "at validation" — false on both counts (no egress policy
on freqtrade pods; v3 policy deliberately allows public 443 because venue IPs live behind
CDNs; validation-time detection of arbitrary network calls is not honestly possible).
Replaced with the deployment truth at that point: gVisor isolation, private networks blocked,
and general outbound HTTPS currently permitted and unsupported. The managed backtest runner
added later is intentionally stricter: it denies all network egress and reads only mounted
Superior datasets. The deployment egress statement does not apply to backtests.

**D21. Paper mode is freqtrade-only at launch.** Nautilus sim execution has zero code today;
`paper_supported` now reads `false` for Polymarket/Lighter, the canonical loop offers a
bounded-live substitute, and Nautilus paper is planned work, not documented behavior.

**D22. Release pinning claimed only where release machinery exists.** Lighter/Polymarket:
immutable releases, live today. Hyperliquid/Binance: `release: null`, mutable backfill
store, reproducibility explicitly not claimed until their pipeline exists. "No gaps array
means not-audited, never no-gaps."

**D23. The `npx @superior-trade/onboard` block removed.** A copy-pasteable command for a
package that would 404 was the most checkable false claim in the docs. The two-call SDK
ceremony (approveAgent + approveBuilderFee, shown inline) is the supported path; the CLI is
planned. Building it is S/M — it should exist before public launch.

**D24. Security page argues with mechanisms, not adjectives.** Named gVisor; named the
secret-store boundary (runtime cluster store, never the application DB); stated the
residual risk plainly — a leaked trade-only key can destroy value up to the account balance
via deliberate bad trades; scoped keys bound a leak, they don't neutralize it. Funding
discipline is part of the security model. Also: `scoped_key: true` is a venue lookup
(derived address ∈ approved agents), not an assurance.

**D25. Smaller corrections from the evals:** Hyperliquid market responses originally carried
framework aliases as the primary symbol. D32 supersedes that: Context `symbol` is venue-native
and framework aliases live under `framework_symbols`. Intelligence `bucket` list corrected
(majors excluded by the engine's
design) and the "same data as candles" claim dropped; `simulated` field added to the metrics
example; `limit_exceeded` added to the error registry; leaderboard example drawdown made
plausible; Free-tier pricing stated ($0) with Pro priced at launch; freqtrade guide now
states the venue scope (HL/Binance only) and the hyperopt/FreqAI boundary in its opening;
HIP-3 defined at first use; a Reliability section added to the runtime overview
(crash-restart, state persistence, positions never auto-closed by infrastructure).

## 2026-07-30 — Minimal-text rework, 繁體中文, stage-1 scope (Jason-directed)

**D26. Reference density, not prose.** Jason: "cut down all the bullshit and text — too hard
to work on." Every content page rewritten to tables/JSON/one-line notes under a strict
contract: all 32 endpoints, every example, table, error code, and honesty caveat preserved;
all aphorisms and philosophy paragraphs deleted. Result: −32% words / −29% lines overall,
with the survivors being mandatory content (JSON, tables, code), not prose. Chrome cut to
match: header is logo + wordmark + language toggle only (no nav links, no Open Terminal, no
"Docs" word); TOC dropped "Was this helpful?" and "Scroll to top"; landing is one line +
title-only cards.

## 2026-07-30 — PR review hardening

**D32. Context uses canonical venue-native symbols.** `/context/markets`, candles, funding,
datasets, and URL path params use `symbol` as the venue-native id. Framework-native names are
aliases in `framework_symbols`, used only inside framework config. Rationale: one primary id
prevents clients from passing a freqtrade pair to a Context endpoint that expects venue data.

**D33. Unsafe BYOK credentials require explicit acknowledgement.** `PUT
/runtime/deployments/:id/credentials` rejects unrestricted or withdrawal-capable credentials
by default with `credential_scope_unsafe`. The override requires
`allow_unscoped_credential`, `acknowledge_withdrawal_risk`, and
`acknowledge_not_recommended` in the request body. Rationale: agents treat 2xx as success;
unsafe custody choices must be visible in input and output.

**D34. Deployment lifecycle actions use a status endpoint.** Metadata stays on
`PATCH /runtime/deployments/:id`; lifecycle transitions use
`PUT /runtime/deployments/:id/status` with `{ "action": "start" | "stop" }`.
Delete force is a request-body acknowledgement, not `?force=true`. Rationale:
validation and destructive behavior should be discriminated by endpoint and body shape,
not inferred from loose metadata fields or query params.

**D35. Money-moving async calls require idempotency and polling.** Managed-wallet withdrawal
now requires `Idempotency-Key`, returns a withdrawal resource, and documents `GET
/wallet/withdrawals/:id` plus list. Rationale: retry after a lost `202` must never
create a second payout.

**D27. Traditional Chinese.** EN/繁 toggle in the header (cookie-based). Content lives in
`content/en/` and `content/zh-Hant/` with per-page English fallback, so a missing
translation never 404s. Nav, chrome strings, search index, and `/md/<path>?lang=zh-Hant`
all localize; llms.txt stays English.

**D28. Stage-1 design scope: Account + Runtime only.** For first-stage design focus the
sidebar, landing, search, and llms.txt show only the Account and Runtime groups
(`stage1` flags in `lib/nav.ts`). Getting Started, Market Context, Guides, and Reference
remain authored and render by direct URL, but are hidden until later stages.

## 2026-07-30 — D26 reversed: full text restored (Jason-directed)

**D29. The tersification (D26) is rolled back.** Jason's call before sharing with the team:
the docs should read like an established API reference (Stripe/Vercel register — complete
sentences, context around every endpoint), not a bare cheat-sheet. All content pages
restored to their pre-tersification (post-honesty-pass) text at `content/en/`. What
_stays_ from the rework: the minimal chrome (D26's header/TOC/landing cuts), the 繁體中文
toggle (D27), and the stage-1 Account+Runtime scope (D28). The terse experiment remains in
git history (`6cf306a3`) if a condensed variant is ever wanted.

## 2026-07-30 — Developer-persona review applied + the two-execution model

**D30. Developer-review fixes.** A developer-persona evaluation (senior quant-shop dev
deciding whether to integrate) surfaced seven must-fixes; all applied: the stage-1 visible
scope is now self-sufficient for a first request (base URL + `x-api-key` + full curls in
`account/registration` and `runtime/deployments`); `alive_until` lapse semantics are
specified, including a new `on_expiry: "stop" | "block_entries"` field (block-entries keeps
exit logic running until flat — the safe expiry for position-holding bots); `code`/`config`
immutability and the live-update path are stated; image dependency contents and create-time
digest pinning documented; a backtest **cost-model table** (fees and builder fee modeled;
slippage and funding NOT — stated plainly); `Idempotency-Key` on all creates plus
`name_taken`; the Polymarket paper-mode contradiction in the Nautilus guide fixed. Also:
per-code HTTP status registry with `x-request-id` on every response, webhooks promoted from
candidate to committed roadmap with an event list, list-response envelopes shown, credential
verification timing (PUT + start) and stop→PUT→start rotation specified, OpenAPI location
declared, UTC reset boundaries stated, and a pass trimming "honest/honesty" self-references
(the reviewer: "Stripe never tells you it's being honest").

**D31. Two kinds of execution (Jason-directed; superseded for `/runtime/executions`).** The original runtime proposal had an explicit split:
**one-time execution** (`/runtime/executions` — a Python script that runs once with
injected credentials and exits; place/close/rebalance/sweep; 15-min cap; `execution_timeout`
and `script_error` codes) and **recurring execution** (deployments, as before). This also
closes the reviewer's "how do I close positions via the API" gap — a close script is a
one-time execution. This script-execution proposal was later replaced by the managed-wallet native action proxy documented under [One-Time Venue Executions](/runtime/executions): callers send `{ venue, action }`, while Superior selects the signing family and owns credentials, signing, nonce, timestamp, and transport. New stage-1-visible **Quick Start** group (Introduction — supported
platforms + the two execution types; Agent — the integration flow request-by-request)
becomes the on-ramp, fixing the reviewer's blocker that stage-1 hid all authentication
context. Site title fixed to "Superior Trade API"; search moved to the header center with
neutral (non-lime) selection.

**D32 (planned, Jason 2026-07-30).** The Quick Start **Agent page becomes a copy-able
prompt**: one block the operator pastes into their AI agent that teaches it the whole
integration (base URL, auth + OTP relay, the two human handoffs, endpoint map, readiness
probes, failure etiquette) — the page's docs prose becomes secondary to that block. Deferred
by Jason ("can come later"); the current request-by-request page stands until then. Natural
implementation: a `<CopyPrompt>` block at the top of `quickstart/agent.md` reusing the
existing copy-button plumbing, with the prompt maintained as its own file so `/md/` serves
it to agents directly.

## 2026-07-30 — Credential model pivot: managed wallets primary, BYOK optional

**D33. D4 amended (Jason-directed).** The public API keeps **Superior-managed trading
wallets (Privy) as the primary credential path** — deposit and deploy, no key handling,
same custody that runs the Terminal — with **BYOK as the option** for self-custody users
and existing venue accounts. Rationale: flexibility at deploy time beats purity; the
managed path is the fastest onboarding and reuses the proven allocate-on-deploy machinery,
while BYOK remains fully specced (toxic-material rules unchanged, scoped-key verification
unchanged) for users who won't hand over custody. Spec shape: `credentials` on create
defaults to `{ "type": "managed" }`; BYOK payloads carry `"type": "byok"`. What D4 removed
from the public surface partially returns: managed-wallet funding/withdrawal semantics
(deposit instructions via `GET /account`, withdrawals restricted to the verified login
wallet). Supported-platforms table now ranked by typical trading volume with venue logos
(Binance > Hyperliquid > Lighter > Polymarket — simple public-volume eval, not a study).

**D34 (2026-07-30).** Follow-ons to D33: the managed wallet gets its own account-level page
(`/wallet/overview` — `GET /wallet` for address/deposit/held-vs-allocated
balances, `POST /wallet/withdraw` to the verified login wallet only, no destination
parameter by design). Site gains **dark/light theme with system default** (pre-paint inline
script, GitHub-Light palette in light mode, cycle toggle system→light→dark in the header).
Landing-section icons via the terminal's Higgsfield crystal-glass pipeline are queued
(blocked on CLI re-auth).

## 2026-07-30 — Phi's API review applied (D35)

**D35.** Five findings from Truong Ma Phi's review of the spec, all accepted and applied:
(1) `POST /account/wallet/withdraw` now **requires** `Idempotency-Key` — money movement
must be retry-safe by construction, not convention. (2) PATCH's action/metadata mixing was
ambiguous under partial failure — lifecycle moved to explicit **`POST …/start` /
`POST …/stop`** endpoints; PATCH edits metadata only (this reverses D30's "fields combine"
convenience — Phi's critique was correct). (3) `DELETE ?force=true` replaced by a two-step
acknowledgement: `409 positions_open` returns a single-use, state-bound `confirm_token`;
the caller repeats DELETE with `X-Confirm-Delete`. (A DELETE request body was considered
per Phi's suggestion and rejected only because proxies drop DELETE bodies unreliably; the
token achieves the same explicit acknowledgement.) (4) Credentials are now one
discriminated union everywhere — `{"type": "managed"}` | `{"type": "byok", "venue", …}`;
omission ≡ managed on deployments, ≡ credential-less on executions (stated, not implied);
`credentials: null` eliminated from all examples. (5) The withdrawal flow is complete:
`GET /account/wallet/withdrawals` + `/:id` with the `queued → processing → completed |
failed` lifecycle and `tx_hash`. New error codes: `idempotency_key_required`,
`invalid_confirm_token`.

**D36 (2026-07-30, Jason-directed).** Per-endpoint **subsections in the sidebar**: the
active page's headings (endpoint `METHOD /path` entries in mono, prose sections in text)
render directly under its sidebar item with scroll-spy highlighting and smooth-scroll
anchors. The right-rail "On this page" TOC is removed — navigation lives in one place.

## 2026-07-30 — Second review round from Phi's PR threads (D37)

**D37.** Five further findings from the PR review threads, all applied: **(a)** unscoped
(master/withdrawal-capable) credentials are now **rejected by default** with `400
unscoped_credential`; the override is an explicit `allow_unscoped: true` body field —
machine-visible, deliberate, never a silent 2xx. This substantially resolves open question
1 at attach time. **(b)** One canonical market identifier: `/context/markets`' `symbol` is
THE id for every `/context` endpoint; framework spellings moved to an `aliases` map used
only in strategy config ("context reads → canonical; strategy config → alias") — the
markets-vs-candles contradiction is gone. **(c)** Executions gained a **sandbox contract**
table: 1 vCPU/1 GiB, ephemeral 512 MiB `/tmp`, package allowlist, gVisor + egress posture
(consistent with D20's honesty), 1 MiB output cap, credential redaction. **(d)** The header
no longer overflows small viewports (fixed rails now `lg:`-only, ⌘K hint hidden on mobile).
**(e)** Hidden pages get full page chrome — breadcrumb/title resolve against the full nav;
neighbors paginate within the visitor's context (staged list for staged pages, full list
for hidden ones) — and `apps/docs` has a working ESLint flat config so `lint` runs.

## 2026-07-31 — Endpoint diet (43→38) + Managed Wallet section (D39)

**D39 (Jason-directed).** Five cuts, Account/Runtime only (Context untouched by choice):
`GET …/deployments/:id/credentials` dropped (duplicate of the deployment GET's embedded
metadata); `GET /account/usage` merged into `GET /account` (one small read for the whole
account picture); `PATCH /account/keys/:id` dropped (names fix at mint; rotation replaces
renaming); `GET …/withdrawals/:id` merged into the list via `?id=`; `DELETE
/runtime/backtests/:id` dropped (12-month retention; re-addable non-breakingly). **A cut
that was proposed and rejected, and the principle behind the rejection:** folding `/logs`
into resource GETs via `?include=logs` was retracted because agent readers have context
windows — resource GETs must stay small by construction, and bulk text (logs, big trade
lists) is always a separate, deliberate fetch. All three `/logs` endpoints stay.

Also per Jason: the managed wallet is promoted from one Account page to its own stage-1
**Managed Wallet** section — Overview (`GET /account/wallet`, held vs allocated,
lifecycle), Deposit (the on-chain flow, rules and edges), Withdraw (`POST …/withdraw` +
the merged withdrawals list). `account/trading-wallet` is removed and all links retargeted.
Crystal-glass wallet icon added to the landing via the terminal icon pipeline.

## 2026-08-01 — Reconciliation with the unified-api implementation (D40)

Two parallel lines of work met on this branch: the docs' D35–D39 passes and the
first `apps/unified-api` implementation. Where they disagreed, the implementation's
choices win, superseding parts of D35/D37 recorded above:

- **Lifecycle**: one endpoint — `PUT /runtime/deployments/:id/status` with
  `{ "action": "start" | "stop" }`. Supersedes D35's separate `POST …/start` /
  `POST …/stop`. `PATCH` stays metadata-only either way.
- **Delete around open positions**: explicit body acknowledgement
  (`force` + `acknowledge_positions_open`), not the D35 `confirm_token` two-step.
  Still never a query flag.
- **Wallet surface**: `GET /wallet`, `GET /wallet/deposits`, `POST /wallet/withdraw`,
  `GET /wallet/withdrawals[/:id]` (not `/account/wallet/*`). Nav group is
  **Managed Wallet** (Jason's naming); page slugs are `wallet/deposits` /
  `wallet/withdrawals`.
- **Unscoped-credential override**: `allow_unscoped_credential` plus the two
  acknowledgement fields, error `credential_scope_unsafe` (supersedes
  `allow_unscoped: true` / `unscoped_credential`).
- **Markets**: framework spellings stay under `framework_symbols`.
- **QA callout dropped** (Jason, 2026-08-01): the boxed Q&A blockquote treatment is
  out; those passages render as plain blockquotes.

## 2026-08-21 — Canonical Markdown URLs for agents

**D41. `.md` is the canonical raw-document URL.** Every documentation page is available at
`/<path>.md` (for example, `/quickstart/agent.md`) with a `text/markdown` content type, and
`/llms.txt` lists those URLs. The original `/md/<path>` route remains supported for existing
clients. Rationale: an explicit file extension is easier for agents and documentation tooling
to identify as Markdown.

## 2026-09-09 — Native venue execution proxy and contract corrections

**D42. One-time execution follows the native venue envelope.** New HTTP and MCP integrations
send `{ "venue": ..., "action": <native venue object> }`; the public schema does not publish
an action-type allowlist. Superior recursively rejects caller credentials, signatures, nonces,
timestamps, headers, methods, paths, and endpoints, then selects a supported signing family and
submits exactly once through an execution-ready managed wallet. The durable lifecycle retains
idempotent replay, uncertain-outcome reconciliation, and `reconciliation_required` when an
outcome cannot be proved. Existing versioned operations remain compatibility inputs, not the
recommended contract. Runtime availability is configuration-dependent: an operational provider
family submits and records supported actions, while an incomplete family fails closed with
`execution_provider_unavailable`. Related new-integration guidance exposes market search only as
`GET /context/markets?query=...&limit=...` and deployment lifecycle changes only as
`PUT /runtime/deployments/{id}/status`; deployment metadata remains on the resource `PATCH`.

## 2026-09-13 — Server-selected dual-mode withdrawal authorization (D43)

**D43. Withdrawal proof follows authenticated login identity.** `GET
/wallet/withdraw/authorization` selects email OTP or wallet signature; callers cannot select
the mode. Email users enter a request-scoped destination and receive a six-digit code bound
to the complete intent for 10 minutes. Wallet users cannot override their locked login-wallet
destination and sign the complete intent as EIP-712 with a five-minute expiry. Both modes run
the side-effect-free `POST /wallet/withdraw/authorize` before funds are prepared, then reuse
the identical body and account-scoped UUID `Idempotency-Key` at `POST /wallet/withdraw`.
Accepted identical requests replay the durable withdrawal even after proof expiry; changed
bound fields conflict. During API-first rollout only, `FEATURE_WITHDRAWAL_OTP=false` hides
policy/OTP/preflight and preserves the prior amount-only final endpoint. Enabled authorization
failures never fall back to that compatibility contract.

## 2026-09-23 — Visible Markdown actions (D44)

**D44. Rendered pages expose both raw-document actions.** The page header provides separate
`View Markdown` and `Copy Markdown` controls. Viewing follows the canonical `/<path>.md` URL in
the current tab, while copying fetches that same URL; both preserve the selected Traditional
Chinese locale. This makes the agent-readable representation discoverable without requiring
readers to know the URL convention.

## Open questions awaiting Jason

1. **D6 override** — hard-require scoped keys for live starts?
2. **Domain** — docs at `docs.superior.trade` with `api.superior.trade/docs` redirecting, or keep docs on the api host?
3. **Deposit floor amounts** — `min_deposit_usd` values in [`/context/venues`](/context/venues) are design placeholders; confirm per venue.
4. **Plan limits** — Free/Pro numbers on [Usage & Limits](/account/usage) mirror today's tiers; confirm they're the go-forward tiers for API-first users.
5. **Copy-trade execution** — shipped as a strategy template on deployments (current design) or as a first-class resource?
6. **Delete vs open positions** — today's stop path auto-closes positions; this design deliberately does NOT (409 `positions_open` + explicit force). Reversing live behavior is a user-safety call — confirm.
7. **Entitlements** — the 3/6 deployment limits are new (current code caps at 10 deployments, 3 trading accounts); a `plan` concept doesn't exist in code yet. Confirm the go-forward numbers and where Pro is sold.
8. **Secret-store bar** — BYOK keys land in Kubernetes Secrets today; is that the accepted bar, or do we require KMS-envelope/sealed secrets before accepting third-party keys?
9. **Where missing compliance/eligibility surface lives** — "an anonymous email buys a trading runtime": geo/KYC/terms posture needs a page, and the policy behind it is not a docs decision.

## How to propose a change

Edit the page in `apps/docs/content/`, and add a dated entry here saying what changed and why. The diff _is_ the design review.
