Commit Graph

71 Commits

Author SHA1 Message Date
255bb070a3 chore(audit-E2): stop stray subpackage lockfiles from coming back
Partial fix for the lockfile drift caught in the audit. The previous
session ran `npm install` inside web/ as a workaround for a Vite vendor-
resolution issue, which left three lockfiles in the wrong places:
  - web/package-lock.json  (npm artifact in a pnpm monorepo)
  - web/pnpm-lock.yaml     (per-package pnpm lockfile, also wrong)
  - backend/pnpm-lock.yaml (same issue)

This commit:
  - Deletes those three files from the working tree.
  - Adds .gitignore entries so they can't be re-committed by accident.
  - Also gitignores .claude/ (Claude Code session metadata).

What's still missing: the root pnpm-lock.yaml needs `react-router-dom`,
`@monaco-editor/react`, `@dnd-kit/{core,sortable,utilities}` added to
its resolution graph. That requires `pnpm install -r --no-frozen-lockfile`
from the repo root on a workstation with GITEA_NPM_TOKEN exported (the
mobile workspace pulls @bytelyst/* private packages from the org's
private registry; this session has no token so the install errors out
on the mobile resolve). It's a one-line follow-up — tracked in
AUDIT_REDESIGN.md item E2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 06:25:31 -07:00
ddbffb6cd1 fix(audit-A): repair the 5 critical broken integrations
A1+A2 — CodeStrategyEditor backtest call
  Was: POST /api/backtest with { symbol, strategyCode, mode: 'code' }
  Now: POST /api/backtest/run with { symbols: [s], strategyConfig: {
       type: 'code', language: 'javascript', code } }
  The backend route is /api/backtest/run (not /api/backtest), and
  /api/backtest/run validates `symbols[]` and `strategyConfig`, not the
  ad-hoc fields we were sending. Also unwraps the { success, results }
  envelope the engine returns and surfaces success:false errors.

A3 — VisualRuleBuilder save shape
  Was: hand-rolled fetch to /api/profiles with { name, symbol, strategyType,
       visualRules, description } — backend's saveTradeProfileForUser ignored
       all of that and either 400'd or persisted a half-empty row.
  Now: uses the canonical createTradeProfile() helper from lib/profileApi
       with the documented TradeProfilePayload shape. Visual rules go inside
       strategy_config.{type:'visual', version:1, rules:[...]} so the engine
       can fan out to a visual interpreter without conflicting with the
       existing rule-based engine. Allocated capital + risk pct pulled from
       botState.settings so the profile inherits the user's current sizing.
       is_active defaults false so the user activates explicitly.

A4+A5 — RightPanel.NewsFeed auth + runtime
  Was: raw fetch() to import.meta.env.VITE_TRADING_API_URL with no
       Authorization header → 401 on every render in any environment that
       requires auth, and prod-broken where the runtime resolver is the
       only source of truth for the API base URL.
  Now: uses fetchNews() from lib/marketApi which already carries the
       platform Bearer token and routes through tradingRuntime.tradingApiUrl.
       Adds an error state in the UI for visibility instead of silently
       leaving the panel blank.

Verified: web/ tsc --noEmit passes. No behavioural change to non-affected
code paths (RightPanel portfolio summary, ResearchView other tabs, etc.).

Refs: docs/AUDIT_REDESIGN.md items A1–A5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 06:23:52 -07:00
4a09d4ba26 docs: add post-redesign systematic audit (52 items across 7 buckets)
Catalogues every gap, bug, and miss found in the web redesign work:
- A: critical broken integrations (wrong endpoint, wrong payload, missing auth)
- B: functional gaps from the original plan (chart indicators, watchlist
  buttons, company name placeholder, etc.)
- C: security & correctness (sandboxing, FMP cache, query-param leakage)
- D: UX/UI polish (skeletons, dark-tab contrast, responsive breakpoints)
- E: build/infra (1 MB bundle, lockfile drift, Monaco workers, README)
- F: test coverage (zero tests for marketApi, builders, screener, endpoints)
- G: mobile parity (none of the new features exist on mobile)

Each row has a severity tag, status box, and a slot for the fix-commit hash.
Subsequent commits will reference items by ID (e.g. fix(A1): ...).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 06:21:30 -07:00
938ed86044 feat: live data wiring (Alpaca/FMP) + strategy builder + screener
Wires the new dashboard to real market data and adds the strategy
builder & screener UIs that were stubbed in the previous commit.

Frontend (web/src/):
- lib/marketApi.ts: authenticated fetch helpers for chart bars,
  market indices, news, and FMP research endpoints
- views/HomeView.tsx: StockChart now fetches live OHLCV via
  fetchChartBars on symbol/period change with loading/error states;
  ResearchCards replaces the static placeholder with live FMP
  profile/metrics/earnings (next-earnings + last 3 historical)
- components/layout/Header.tsx: live SPY/DIA/QQQ price + change%
  via fetchMarketIndices, refreshing every 60s; removed unused
  static sparkline placeholder
- components/strategy/VisualRuleBuilder.tsx: drag-and-drop IF/THEN
  rule composer using @dnd-kit (RSI/MACD/EMA/Price/Volume,
  above/below/crosses, BUY/SELL with shares or % of capital);
  saves via POST /api/profiles
- components/strategy/CodeStrategyEditor.tsx: Monaco editor with
  JS strategy template; "Run Backtest" posts to /api/backtest and
  renders return/win-rate/Sharpe/drawdown plus trade log
- views/ResearchView.tsx: adds "Visual Builder" and "Code Editor"
  sub-tabs alongside Strategies / Signals / Backtesting
- views/ScreenerView.tsx: live FMP screener with market-cap and
  sector filters, sortable columns, click-to-load-symbol routing
- index.css: light theme background; @keyframes spin for loaders
- App.dom.test.tsx: rewritten for router-based AppShell (was
  asserting on the removed tab UI; fixes 5 prior failures)

Backend (backend/src/services/apiServer.ts):
- /api/chart/bars: detects crypto symbols (contains "/") and
  routes to Alpaca v1beta3/crypto/us/bars; equities use
  v2/stocks/{symbol}/bars with iex feed
- (existing) /api/news, /api/market/indices, /api/research/{
  profile,metrics,earnings}, /api/screener proxy endpoints

Build/config:
- web/vite.config.ts: dedupe react / react/jsx-runtime /
  react-router-dom so the vendored react-auth dist resolves the
  same React instance (fixes "Cannot resolve react/jsx-runtime"
  Rollup error)
- web/tsconfig.app.json: exclude shared/platform-clients.ts and
  shared/platform-mobile.ts (mobile-only, missing RN SDK)
- web/package.json: add react-router-dom, @monaco-editor/react,
  @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities

Verification: `npm run build` in web/ → clean (✓ built in 3s);
backend tsc --noEmit → clean. Test suite: 151/155 pass; the 4
remaining failures are pre-existing (3 useTabFeatureFlags module
cache leaks, 1 EntryForm), not introduced here.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 06:16:46 -07:00
f62c3b15ee feat: full web dashboard redesign + 6 new API proxy endpoints
Replaces the 12-tab dashboard with a 3-column layout matching the
investing app mockup (sidebar nav, main chart area, right panel).

Web changes:
- New context/AppContext.tsx — shared botState/auth across all views
- New layout: Sidebar, Header (with market index sparklines), RightPanel
- New views: Home, Portfolio, Research, Markets, Screener, Watchlist, Alerts, Settings
- AppShell wires React Router routes to all views
- App.tsx refactored to use AppContext.Provider + BrowserRouter

Backend changes:
- 6 new proxy endpoints: /api/news, /api/market/indices,
  /api/research/profile, /api/research/metrics,
  /api/research/earnings, /api/screener
- config/index.ts: FMP_API_KEY env var added

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 23:50:01 -07:00
d955d00c00 feat(contracts): shared socket namespaces, tab flags, cutover docs, README
- shared/realtime.ts: add SOCKET_NAMESPACES constants (/trading, /admin, root)
- shared/feature-flags.ts: add tabs.marketplace and tabs.membership to
  TradingFeatureFlagsResponse; add FEATURE_FLAG_KEYS constants
- .env.example: remove /api suffix from VITE/NEXT_PUBLIC trading URL vars
  (web appends /api itself); add tab visibility flag vars with comments
- web: add useTabFeatureFlags hook + DOM test; wire tab visibility into App.tsx
- web/vite.config.ts: finalize build config
- mobile/providers/TradingDataProvider.tsx: deriveSocketParams for proxy-safe
  socket origin/path resolution (already landed upstream, conflict resolved)
- docs: add CUTOVER_WEB.md, CUTOVER_MOBILE.md checklists; update OPERATIONS.md
  with Docker commands and resolved gap log; update ROADMAP.md to Done;
  add BACKEND_AUDIT_SCHEMA.md, BACKEND_API_DEPRECATION.md, CONVENTIONS.md;
  add audit-events container entry to AZURE_INFRASTRUCTURE.md
- README.md: full rewrite with workspace table, arch summary, env var reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:35:53 -04:00
6c43fca934 chore(infra): vendored @bytelyst/* packages, Docker healthcheck, compose merge
- Switch @bytelyst/* to file:../vendor/* references; add vendor/ tree;
  update both Dockerfile stages to COPY vendor/ before pnpm install
- docker-compose.yml: add healthcheck on backend /health/live; use
  backend/.env as env_file; env-var-driven web build args with prod defaults;
  GITEA_NPM_TOKEN uses ${:-} safe default; web depends_on service_healthy
- Add docker-compose.dev.yml hot-reload overlay
- Add scripts/dev.sh convenience script for Docker+local-web hybrid
- .npmrc: add replace-registry-host=always for Gitea Docker-internal rewrite
- Update smoke-release.sh and root package.json docker:* scripts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:35:35 -04:00
4cfb446f57 feat(backend): WebSocket namespaces, audit persistence, tab flags, telemetry
- Add /trading and /admin named Socket.IO namespaces; root namespace kept for
  backward compat; admin namespace rejects non-admins at connect time
- Wire auditRepository.ts: persist TradeAuditEvent to Cosmos audit-events
  container (best-effort); expose GET /api/admin/audit for admin queries
- Add tradingTelemetry singleton (Node.js Map-based storage adapter); init
  and fatal-error tracking wired in index.ts main()
- Add TAB_MARKETPLACE_ENABLED / TAB_MEMBERSHIP_ENABLED config flags; expose
  tabs.* shape in GET /api/feature-flags response
- Fix SupabaseService URL validation (regex check before createClient)
- Wire check:api-contract and check:audit-repository into npm run test
- Switch @bytelyst/* deps to file:../vendor/* references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 19:35:00 -04:00
root
e2008f70b9 fix: web + mobile pre-beta audit — real APIs, socket routing, empty states
Web:
- runtime.ts: use import.meta.env (process.env is undefined in Vite browser bundle)
- tradingApiUrl local fallback: drop /api suffix (API libs already append /api/*)
- useWebSocket: deriveSocketParams() — correctly splits origin + socket path for
  Caddy handle_path /invttrdg/* proxy (io(origin, {path}), not io(url-with-path))
- App.tsx: pass socket prop to AdminTab; pass connected prop to SignalsTab
- AdminTab: remove duplicate useWebSocket; accept socket as prop
- SignalsTab: connection-aware empty state message
- backtest/flags: default to disabled when VITE_BACKTEST_ENABLED unset
- EntryForm: NaN guard before live trade execution
- MarketplaceTab: null-safety on symbols.rules access
- Tests: pass socket prop to AdminTab; update empty state assertion

Mobile:
- TradingDataProvider: same deriveSocketParams fix — EXPO_PUBLIC_SOCKET_PATH
  overrides auto-derived path from tradingApiUrl
- strategies: replace mock data with real GET /api/profiles + PATCH active toggle
- chat: wire to real POST /api/chat; remove hardcoded mock reply
- marketplace: fetch GET /api/marketplace-presets; USE STRATEGY calls POST /api/profiles
- settings: sign-out confirmation dialog; execution mode read-only hint;
  version from expo-constants instead of hardcoded v2.3
- positions/history: empty state UI when no data
- CustomTabBar: always show tab labels (not only when focused)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 04:50:51 +00:00
root
f0a6ce09ff feat(web): Dockerize web app, wire to deployed backend
- Add web/Dockerfile (node:20 builder + nginx:alpine, port 3085)
- Add web service to docker-compose.yml with VITE_ build args
- Create web/.env and mobile/.env pointing to api.bytelyst.com
- Backend port mapping: 4025:4018 (4018 reserved by actiontrail)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 17:48:17 +00:00
root
b2f037c77d chore(deploy): Node 20, port 4025, registry deps, platform network
- Upgrade Dockerfile base from node:18 to node:20 (fixes crypto global)
- Map host port 4025 → container 4018 (4018 taken by actiontrail)
- Join learning_ai_common_plat_default Docker network for platform service
- Switch all @bytelyst/* link: deps to registry versions
- Bump @bytelyst/llm to ^0.1.1 (adds createFallbackChain, GeminiProvider etc)
- Regenerate pnpm-lock.yaml against Gitea registry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 17:23:49 +00:00
5e07ac040d feat: make backend Docker-ready and web Vercel-ready
- Switch @bytelyst/* deps from link: to private Gitea registry (^0.x)
- Add .npmrc pointing to gitea.bytelyst.com private npm registry
- Rewrite backend/Dockerfile: monorepo root context, pnpm workspace,
  correct EXPOSE 4018, CMD node dist/backend/src/bootstrap.js
- Move vercel.json to repo root with pnpm filter build commands
- Remove web/Dockerfile and web/nginx.conf (web is Vercel-only)
- Remove web service from docker-compose.yml (backend Docker only)
- Document GITEA_NPM_TOKEN requirement in .env.example
- Fix start script path: dist/backend/src/bootstrap.js (rootDir: "..")

PREREQUISITE: Set GITEA_NPM_TOKEN and run pnpm install to regenerate
pnpm-lock.yaml before first Docker build.

Vercel settings: Root Directory = repo root, add GITEA_NPM_TOKEN env var.
Docker build: GITEA_NPM_TOKEN=<token> docker compose build

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 19:05:35 -07:00
a256571480 docs(azure): mark KV wiring and AzureOpenAI items complete in audit log
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 18:29:13 -07:00
aaa516122e feat(backend): wire Azure Key Vault secret resolution at startup
- Add bootstrap.ts as new entry point — resolves Key Vault secrets via
  DefaultAzureCredential before config/index.ts is evaluated, so all
  process.env reads pick up KV values (Azure CLI in dev, Managed Identity
  in prod). Falls back to .env if AZURE_KEYVAULT_URL is not set.
- Define INVTTRDG_SECRETS mappings for Cosmos, Azure OpenAI, product-id
- Add AZURE_OPENAI_ENDPOINT / KEY / DEPLOYMENT to config
- aiClient: prefer AzureOpenAIProvider (AI Foundry) when Azure OpenAI
  config is present; falls back to direct OpenAI if not configured
- Add @azure/identity, @azure/keyvault-secrets, @bytelyst/config deps
- Update dev/start scripts to use bootstrap.ts entry point
- Document AZURE_KEYVAULT_URL and Azure OpenAI vars in .env.example

Key Vault: https://kv-mywisprai.vault.azure.net/
Secrets prefix: invttrdg-*

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 18:28:47 -07:00
bb59b918d6 docs(azure): add infrastructure audit doc for invttrdg Azure resources
Records Cosmos DB setup (12 containers), Azure OpenAI deployments (gpt-4o,
gpt-4o-mini), Key Vault secrets, and pending work items.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 13:18:38 -07:00
c3651f5696 feat(backend): replace custom aiClient with @bytelyst/llm platform package
- Import PerplexityProvider, OpenAIProvider, GeminiProvider from @bytelyst/llm
- Use createFallbackChain() instead of manual axios fallback loop
- Remove axios and @types/axios — no longer needed
- Preserve AIClient class interface (generateAnalysis, getProviderHealth) —
  no changes required in apiServer.ts or AIAnalysisRule.ts
- Fallback order still driven by config.AI.FALLBACK_LIST

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 12:50:34 -07:00
bcb6bf4d71 docs(roadmap): mark root backend script legacy Supabase audit done
Made-with: Cursor
2026-04-04 20:47:43 -07:00
ac5d91c9ef docs: list backend root scripts still importing SupabaseService
Made-with: Cursor
2026-04-04 20:44:26 -07:00
6fac10de9d refactor(backend): root scripts use legacySupabase client where possible
- Call loadDynamicConfig() without dead supabaseService argument (Cosmos-backed).
- Use getLegacySupabaseClient() for raw .from() queries in maintenance scripts.
- manualOverrideCloseTrades: typed imports + legacy client for lifecycle SELECT.
- verify_realtime: ESM .js imports and comment for subscribeToProfiles.
- verifyTenantIsolation: comment for singleton monkey-patch.

Made-with: Cursor
2026-04-04 20:44:24 -07:00
eb70ef6c03 docs(roadmap): sync snapshot with legacy access and contract cleanup
Made-with: Cursor
2026-04-04 20:34:23 -07:00
7884639876 refactor(backend): route legacy Postgres access through legacySupabaseClient
Made-with: Cursor
2026-04-04 19:30:15 -07:00
72ec663125 refactor(backend): extract UserConfig to tradingUserTypes
Made-with: Cursor
2026-04-04 19:02:45 -07:00
12cedd12da fix(backend): route alerts admin scoping through isTradingAdmin
Made-with: Cursor
2026-04-04 18:58:06 -07:00
b306f3264e refactor(backend): extract shared trading persistence types from SupabaseService
Made-with: Cursor
2026-04-04 18:56:20 -07:00
774541289a refactor(backend): resolve legacy Supabase client inside capital ledger repository
Made-with: Cursor
2026-04-04 18:53:29 -07:00
f0dd2055bf refactor(backend): resolve legacy Supabase client inside user, profile, and snapshot repositories
Made-with: Cursor
2026-04-04 18:47:23 -07:00
b632a0d946 refactor(backend): resolve strategy preset legacy client inside repository
Made-with: Cursor
2026-04-04 18:28:35 -07:00
9898289974 chore(backend): clarify legacy Supabase disabled diagnostic
Made-with: Cursor
2026-04-04 18:28:19 -07:00
1b8740a7f5 fix(backend): align startup logs and validateConfig with Cosmos-first user store
Made-with: Cursor
2026-04-04 18:23:34 -07:00
b4d312ce74 refactor: remove dynamic config legacy fallback 2026-04-04 18:13:41 -07:00
5bba149a7b refactor: share feature flag contract across backend and web 2026-04-04 18:10:34 -07:00
d99cb94d19 feat: standardize request ids across operator flows 2026-04-04 18:07:43 -07:00
ffa60fcfb7 refactor: remove live web supabase dependency 2026-04-04 18:03:49 -07:00
f73f855eb0 fix: align web verification with platform session contracts 2026-04-04 18:00:30 -07:00
5d3be081ee refactor: move runtime trading records to cosmos 2026-04-04 17:48:49 -07:00
e043f3c79d refactor: move user metadata and presets onto cosmos paths 2026-04-04 17:24:55 -07:00
0baf32bfcf feat: add explicit feature flag contract 2026-04-04 17:18:20 -07:00
77c7b32ac0 refactor: seed cosmos stores and standardize request ids 2026-04-04 17:16:18 -07:00
790213513f test: add release smoke coverage and runbook 2026-04-04 17:07:48 -07:00
6c39b9b185 refactor: move web auth onto platform session helpers 2026-04-04 17:07:42 -07:00
541c617717 refactor: move history tab behind backend apis 2026-04-04 16:52:06 -07:00
b433686776 refactor: move web trading data behind backend apis 2026-04-04 16:49:18 -07:00
560c95a599 refactor: move capital ledger to cosmos-first repository 2026-04-04 16:37:54 -07:00
5c4c001f35 refactor: move distributed locks to cosmos-first repository 2026-04-04 16:33:27 -07:00
733874bb6d refactor: move backend snapshots to cosmos-first repository 2026-04-04 16:30:53 -07:00
1f2b7bdf89 refactor: align reconciliation runtime flows with repository 2026-04-04 16:28:59 -07:00
d1da7ec70c refactor: route backend order history access through repository 2026-04-04 16:25:46 -07:00
2b36fca143 refactor: move backend boot user discovery into repositories 2026-04-04 16:18:27 -07:00
50defe1890 refactor: centralize backend profile metadata lookups 2026-04-04 16:12:41 -07:00
ebaabaed47 feat: move manual entries behind backend api 2026-04-04 16:09:21 -07:00