The Plans page (/plans) had multiple known overflow / clipping bugs:
1. .saved-setup-card { overflow: hidden } clipped the right-side action
buttons (Edit, Delete) on cards with long content.
2. .saved-setup-meta-grid chips used white-space: nowrap + overflow: hidden
+ text-overflow: ellipsis, which truncated each chip awkwardly instead
of wrapping. Long Trade ID and Order ID badges blew out the card.
3. .saved-setup-topline used a CSS Grid with auto column for actions, so
actions could push the title block off-screen at narrow widths.
4. .saved-setup-timeline used 5 fixed-min-width columns that caused
horizontal overflow on cards <440px wide.
5. The outer two-column grid forced minmax(380px, ...) on the saved-setups
column which squeezed the form on 1280–1440px screens.
6. The critical alert banner used a loud high-contrast red background and
uppercase letterspaced text — visually inconsistent with the rest of
the app.
Fixes applied in web/src/layout-fixes.css (extends existing layout fixes):
- saved-setup-card → overflow visible, never clip children.
- saved-setup-topline → flexbox with flex-wrap, title flexes to 320px
before actions wrap below to a new row.
- saved-setup-actions → flex-wrap with right-justified items.
- saved-setup-meta-grid chips → real wrapping (white-space: normal,
overflow visible, max-width 100%, line-height tightened, padding
expanded slightly for readability).
- Trade-id badges → break-all so long IDs wrap inside their pill.
- saved-setup-timeline → overflow-x: auto so progression scrolls
inside the card on narrow widths instead of pushing the layout.
- Outer grid → single column below 1440px, two-column 1.15fr/0.85fr
above. Form gets adequate width on common laptop sizes.
- Alert banner → soft tinted background using card+destructive mix,
normal weight, no uppercase, integrated with the app shell aesthetic.
- saved-setups-header, asset-row, form sections → flex-wrap + min-width: 0
so nothing forces horizontal scroll.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
||
|---|---|---|
| .vscode | ||
| .windsurf/workflows | ||
| backend | ||
| docs | ||
| mobile | ||
| scripts | ||
| shared | ||
| web | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .npmrc | ||
| .npmrc.docker | ||
| docker-compose.dev.yml | ||
| docker-compose.yml | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.base.json | ||
| vercel.json | ||
ByteLyst Investment Trading
Canonical monorepo for the ByteLyst trading product. Contains the backend trading engine, web dashboard, and Expo mobile app under a single pnpm workspace.
Workspaces
| Package | Path | Description |
|---|---|---|
@bytelyst/trading-backend |
backend/ |
Node.js trading engine, REST API, Socket.IO |
@bytelyst/trading-web |
web/ |
React 19 dashboard (Vite) |
@bytelyst/trading-mobile |
mobile/ |
Expo 54 React Native companion app |
| shared types | shared/ |
Cross-surface constants, interfaces, and helpers |
Core Principles
- Backend-authoritative state — all trading state (orders, positions, capital) lives in the backend; web/mobile only read and display
- Platform-service for auth (platform JWT), kill-switch, telemetry, and feature flags
- Cosmos DB is primary — Azure Cosmos DB is the production control-plane store; Supabase is legacy fallback only
- No duplicated bootstrap — auth, kill-switch, and telemetry bootstrap run once per surface via shared contracts
- Trading domain stays product-owned — strategy logic, risk rules, and execution never move to common-platform packages
Quick Start
pnpm run install:common-plat
cp .env.example .env # root — used by Docker Compose and CI
cp backend/.env.example backend/.env # backend — fill in Cosmos, exchange, and AI credentials
cp web/.env.example web/.env.local # web — Vite build-time API URLs
cp mobile/.env.example mobile/.env.local # mobile — Expo build-time API URLs
pnpm verify # typecheck + test + strict UI audit + build — must be green before any deploy
Common Commands
# Verification (run before every merge / deploy)
pnpm verify # typecheck + test + strict UI audit + build across all surfaces
pnpm lint # backend contract + security guards + web/mobile lint
pnpm smoke:release # auth + kill-switch smoke tests
# Development
pnpm --filter @bytelyst/trading-backend dev # backend hot-reload (tsx)
pnpm --filter @bytelyst/trading-web dev # web Vite dev server
pnpm --filter @bytelyst/trading-mobile dev # Expo dev server
# Docker
pnpm docker:up # production — build images, start backend + web
pnpm docker:dev # dev overlay — hot-reload for backend and web
pnpm docker:down # stop all containers
Backend Verification Scripts
Beyond pnpm verify, the backend has targeted contract and safety checks:
cd backend
npm run check:api-contract # feature-flag shapes, audit events, namespace constants
npm run check:websocket-contract # BotState lifecycle consistency
npm run check:security-guards # tenant isolation
npm run check:tenant-isolation # row-level access scoping
npm run check:strict-capital-guard # capital invariant enforcement
npm run check:lifecycle-regressions # trade lifecycle regression suite
Full list in backend/package.json under scripts.
Architecture
The backend trading loop polls every POLLING_INTERVAL (default 60 s). For each
user → profile → symbol it runs the 7-rule ProStrategyEngine, then routes signals
through AutoTrader → riskEngine → TradeExecutor → exchange connector.
7-Rule Pipeline (backend/src/strategies/rules/):
TrendBiasRule— EMA 50/200 trend filterSessionRule— market hours gatingZoneRule— price proximity to S/R zonesMomentumRule— RSI confirmationEntryTriggerRule— EMA reclaim / pattern detectionRiskManagementRule— ATR-based stop sizingAIAnalysisRule— LLM sentiment (Perplexity → OpenAI → Gemini fallback)
WebSocket namespaces (shared/realtime.ts):
/trading— all authenticated users; user-scoped BotState/admin— admin-only; full cross-user state; non-admins rejected at connect/(root) — backward-compatible default
Persistence — Azure Cosmos DB (primary) for all runtime paths. Supabase is a legacy
fallback for one-off reconciliation scripts only (documented in
docs/BACKEND_LEGACY_SUPABASE_SCRIPTS.md).
Documentation
| Doc | Purpose |
|---|---|
docs/PRD.md |
Product vision, scope, and platform integration boundaries |
docs/ROADMAP.md |
Phase tracker and implementation snapshot |
docs/OPERATIONS.md |
Local dev, Docker, verification, staged cutover, rollback rules |
docs/CONVENTIONS.md |
Naming, directory structure, and import boundary rules |
docs/BACKEND_AUDIT_SCHEMA.md |
TradeAuditEvent schema and event catalogue |
docs/BACKEND_API_DEPRECATION.md |
Full endpoint catalogue, WebSocket namespaces, deprecation policy |
docs/BACKEND_LEGACY_SUPABASE_SCRIPTS.md |
Legacy Supabase script inventory |
docs/CUTOVER_WEB.md |
Stage 2 — internal web adoption checklist |
docs/CUTOVER_MOBILE.md |
Stage 3 — mobile internal beta checklist |
docs/AZURE_INFRASTRUCTURE.md |
Azure resource and Key Vault setup |
Environment Setup
Each surface has its own .env.example. The root .env.example is the comprehensive reference covering all surfaces and is used by Docker Compose and CI:
| File | Usage |
|---|---|
.env.example |
Root — Docker Compose, CI, complete reference for all variables |
backend/.env.example |
Copy to backend/.env — trading engine config, secrets, feature flags |
web/.env.example |
Copy to web/.env.local — Vite build-time vars (API URLs, feature overrides) |
mobile/.env.example |
Copy to mobile/.env.local — Expo build-time vars (API URLs) |
Minimum backend variables to run locally:
| Variable | Required | Description |
|---|---|---|
COSMOS_ENDPOINT / COSMOS_KEY / COSMOS_DATABASE |
Yes | Primary data store (see docs/AZURE_INFRASTRUCTURE.md) |
PLATFORM_API_URL |
Yes | Platform-service base URL |
PLATFORM_AUTH_ENABLED |
— | true for platform JWT (RS256); false for local dev with JWT_SECRET |
PLATFORM_JWT_PUBLIC_KEY or PLATFORM_JWT_JWKS_URL |
Prod | Platform JWT verification key |
JWT_SECRET |
Dev | Legacy/local JWT secret when PLATFORM_AUTH_ENABLED=false |
ALPACA_API_KEY / ALPACA_API_SECRET |
For trading | Exchange credentials |
FMP_API_KEY |
For research/screener | Financial Modeling Prep key required by /api/research/* and /api/screener; the shared demo key is intentionally rejected by the backend |
OPENAI_API_KEY |
For AI rules | Primary LLM provider |
ENABLE_TRADING |
— | Set true to enable live order execution (default false) |
PAPER_TRADING |
— | Set true for paper mode |
AZURE_KEYVAULT_URL |
Prod | Enables auto-resolution of invttrdg-* secrets at startup |
Financial Modeling Prep requires apikey query-string authentication, so the
backend keeps all FMP calls server-side, rejects the shared demo key, caches
FMP responses for 30 minutes, hashes cache keys instead of storing raw URLs, and
uses redacted URL helpers for any future FMP log output.
Shared Dependencies
Package resolution is controlled by BYTELYST_PACKAGE_SOURCE through
.pnpmfile.cjs.
common-plat(default): resolve@bytelyst/*directly from the siblinglearning_ai_common_platcheckout, or fromBYTELYST_COMMON_PLAT_ROOT.vendor: prefervendor/bytelyst/*, then fall back to the siblinglearning_ai_common_platcheckout.
Examples:
pnpm run install:common-plat
pnpm run install:vendor
pnpm run check:packages
Override the sibling repo location with BYTELYST_COMMON_PLAT_ROOT=/path/to/learning_ai_common_plat.
Release Checklist
pnpm verify && pnpm lint && pnpm smoke:release
All three must be green. See docs/OPERATIONS.md for the full go/no-go criteria and
the staged cutover sequence (backend → web → mobile → production).