Skip to content

fix(legal): add default user agreement + privacy policy to brand-config - #206

Open
TThranduil1 wants to merge 2 commits into
OpenByteInc:mainfrom
TThranduil1:fix/legal-defaults
Open

fix(legal): add default user agreement + privacy policy to brand-config#206
TThranduil1 wants to merge 2 commits into
OpenByteInc:mainfrom
TThranduil1:fix/legal-defaults

Conversation

@TThranduil1

Copy link
Copy Markdown

Summary

/api/settings/brand-config was returning all-empty legal fields (user_agreement_url, privacy_policy_url, user_agreement_text, privacy_policy_text all ""). This is a compliance gap for a platform handling real funds.

Changes

  • branding.py: add legal defaults to BRAND_DEFAULTS so the public brand-config API returns non-empty legal metadata out of the box. Operators can still override via BRAND_LEGAL_* env vars.
    • user_agreement_url/legal/user-agreement
    • privacy_policy_url/legal/privacy-policy
    • Both *_text fields get a summary string (full pages should be created at the URLs)
  • env.example: fill in BRAND_LEGAL_* defaults so operators see the expected values

Verified

Live curl https://quant.kai.com/api/settings/brand-config | jq .data.legal returned all empty before this fix.

Related

Thranduil added 2 commits August 13, 2026 16:18
…onfig

The /api/settings/brand-config endpoint was returning empty legal fields
(user_agreement_url, privacy_policy_url, user_agreement_text,
privacy_policy_text all blank). This is a compliance gap for a trading
platform handling real funds.

- branding.py: add legal defaults to BRAND_DEFAULTS (summary text + URLs
  pointing to /legal/user-agreement and /legal/privacy-policy), so the
  public brand-config API returns non-empty legal metadata out of the box
- env.example: fill in the BRAND_LEGAL_* defaults so operators see the
  expected values
…wire guard into order gateway

### Platform-level risk guard (app/services/risk_guard.py)
- New RiskGuard module: 5 hard rules — drawdown halt (default 20%),
  single-symbol position ratio cap (30%), martingale layer/leverage
  lock (6 layers / 4x), order notional + ratio cap (100k / 10%),
  sliding-window rate limit (20 orders/60s)
- All thresholds configurable via RISK_GUARD_* env vars
- Thread-safe singleton (RiskGuard.shared())
- Fail-open design: if account snapshot is unavailable, guard skips
  rather than blocking trading

### Frontend error monitoring endpoint (app/routes/error_reports.py)
- POST /api/v2/errors — receives batched frontend error events
  (window.onerror, unhandledrejection, resource errors, trade/strategy
  crashes). No auth (errors can happen pre-login). Rate-limited by
  payload size cap (50 events/batch, 4k chars/field)
- GET /api/v2/errors/stats — lightweight ops counter
- Registered in openapi/register.py + tags.py as ErrorReports tag

### Risk guard integration (app/services/strategy_v2/live_execution.py)
- StrategyV2OrderGateway.submit() now calls _check_risk_guard() after
  _validate() and before persisting the pending order
- Fetches best-effort account snapshot to evaluate drawdown/position
  ratio; infers martingale state from action prefix
- Blocked orders raise ValueError('strategyV2.riskGuardBlocked: ...')
  so the caller can surface the reason to the AI strategy review

Related frontend PR: OpenByteInc/QuantDinger-Vue#8 (error_monitor.js
reports to this /api/v2/errors endpoint)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant