learning_ai_invt_trdg/docs/CONVENTIONS.md
Saravana Achu Mac 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

228 lines
9.9 KiB
Markdown

# Repository Conventions
## Purpose
This document defines naming conventions, directory structure rules, and import boundaries
for `learning_ai_invt_trdg`. It is the authoritative reference for where code lives and
what each package is allowed to import.
---
## Package Names
| Package | Name in `package.json` | `pnpm --filter` alias |
|---|---|---|
| Backend | `@bytelyst/trading-backend` | `trading-backend` |
| Web | `@bytelyst/trading-web` | `trading-web` |
| Mobile | `@bytelyst/trading-mobile` | `trading-mobile` |
| Shared | `@bytelyst/trading-shared` (internal — not published) | — |
---
## Directory Structure
```
learning_ai_invt_trdg/
├── backend/
│ ├── src/
│ │ ├── backtest/ # Backtesting engine and guards
│ │ ├── config/ # Environment config loader (config/index.ts is the only place process.env is read)
│ │ ├── connectors/ # Exchange connectors (Alpaca, CCXT) + factory
│ │ ├── domain/ # Trading domain enums, value types, and pure domain logic
│ │ ├── repositories/ # Cosmos DB data-access layer (one file per entity)
│ │ ├── scripts/ # Internal one-time scripts and verification contracts (not imported by src/)
│ │ ├── services/ # Application services (apiServer, TradeExecutor, aiClient, etc.)
│ │ ├── strategies/ # 7-rule ProStrategyEngine and individual rule implementations
│ │ └── utils/ # Generic utilities (logger, symbolMapper, etc.)
│ ├── *.ts # Root-level verification / reconciliation scripts (not part of the runtime)
│ └── package.json
├── web/
│ └── src/
│ ├── backtest/ # Backtest feature: hook, flags, UI components
│ ├── components/ # Shared React components (AuthContext, Login, ChatControl, etc.)
│ ├── hooks/ # React hooks (useWebSocket, useTabFeatureFlags, etc.)
│ ├── lib/ # Utility modules: authSession, runtime, profileApi, etc.
│ ├── tabs/ # Top-level tab components (one file per tab)
│ ├── test/ # Vitest test setup and fixtures
│ ├── App.tsx # Root component: tab routing, auth gate, feature flags
│ └── main.tsx # Vite entry point
├── mobile/
│ ├── app/ # Expo Router file-based routes
│ │ ├── (tabs)/ # Tab screens: index, positions, history, strategies, settings
│ │ ├── _layout.tsx # Root layout (auth gate, kill-switch)
│ │ ├── chat.tsx # AI chat surface
│ │ └── marketplace.tsx # Marketplace surface
│ ├── components/ # React Native shared components
│ ├── hooks/ # React Native hooks
│ ├── lib/ # runtime, telemetry, authSession equivalents
│ ├── providers/ # MobileAuthProvider, TradingDataProvider
│ └── utils/ # Utility functions
├── shared/ # Cross-surface constants and TypeScript interfaces
│ ├── feature-flags.ts # TradingFeatureFlagsResponse, TabFeatureFlags, BacktestFeatureFlags
│ ├── realtime.ts # SOCKET_NAMESPACES, buildTradingSocketOptions, isUnauthorizedSocketError
│ ├── request-id.ts # createRequestId()
│ ├── runtime.ts # getRuntimeEnvironment()
│ ├── product.ts # productConfig — canonical product identity
│ ├── control-plane.ts # Control-plane state types
│ ├── platform-web.ts # Web-specific platform helpers
│ └── platform-mobile.ts # Mobile-specific platform helpers
├── docs/ # All project documentation
├── scripts/ # Root-level build/verify scripts
└── vendor/ # Local vendored @bytelyst/* packages (symlinked or copied)
```
---
## Import Boundary Rules
### Rule 1 — `shared/` is the only cross-surface code
No surface may import directly from another surface's `src/`.
| Importer | May import from |
|---|---|
| `backend/src/` | `shared/`, `vendor/bytelyst/*`, npm packages |
| `web/src/` | `shared/`, `vendor/bytelyst/*`, npm packages |
| `mobile/` | `shared/`, `vendor/bytelyst/*`, npm packages |
| `shared/` | npm packages only — never from backend, web, or mobile |
**Violation example (never do this):**
```ts
// In web/src — WRONG
import { TradeExecutor } from '../../../backend/src/services/TradeExecutor.js';
```
### Rule 2 — `config/index.ts` is the only `process.env` reader in the backend
All environment variable access in `backend/src/` goes through `config/index.ts`.
No other file calls `process.env` directly. This makes the config surface auditable
and testable in isolation.
### Rule 3 — `domain/` contains no I/O
`backend/src/domain/` is pure TypeScript: enums, value types, and functions with no
database calls, no HTTP, and no filesystem access. It may be imported by any other
backend module.
### Rule 4 — `repositories/` only talk to Cosmos
`backend/src/repositories/` (or `services/*Repository.ts`) are the only files that
import `@azure/cosmos` or call Cosmos client methods. Services and strategies call
repositories; they do not call Cosmos directly.
### Rule 5 — `scripts/` are not imported at runtime
`backend/src/scripts/` contains verification contracts (e.g., `verifyWebsocketContract.ts`)
that run as standalone processes. They are never `import`-ed by `backend/src/index.ts`
or any other runtime module. Root-level `backend/*.ts` scripts follow the same rule.
### Rule 6 — `shared/` exports must be serialisable
Everything exported from `shared/` must be importable in all three environments:
Node.js (backend), browser (web), and React Native (mobile). No Node.js built-ins,
no DOM APIs, no React Native-specific APIs.
### Rule 7 — Trading domain logic stays in the backend
No trading strategy logic, risk rules, capital guard calculations, or execution logic
may be moved into `shared/`, `web/`, or `mobile/`. Backend is authoritative.
---
## Naming Conventions
### Files
| Context | Convention | Example |
|---|---|---|
| TypeScript source | `camelCase.ts` | `apiServer.ts`, `healthTracker.ts` |
| React components | `PascalCase.tsx` | `OverviewTab.tsx`, `AuthContext.tsx` |
| React hooks | `use` prefix, `camelCase.ts` | `useWebSocket.ts`, `useTabFeatureFlags.ts` |
| Test files | `.test.ts` / `.test.tsx` | `App.dom.test.tsx` |
| Verification scripts | `verify*.ts` / `test*.ts` | `verifyApiContract.ts` |
| Docs | `SCREAMING_SNAKE.md` | `CONVENTIONS.md`, `OPERATIONS.md` |
### Identifiers
| Context | Convention | Example |
|---|---|---|
| Classes | `PascalCase` | `ApiServer`, `TradeExecutor` |
| Interfaces / types | `PascalCase` | `TradingFeatureFlagsResponse`, `BotState` |
| Constants (module-level) | `SCREAMING_SNAKE_CASE` | `SOCKET_NAMESPACES`, `BACKTEST_FLAG_KEYS` |
| Functions | `camelCase` | `buildTradingSocketOptions`, `createRequestId` |
| React components | `PascalCase` | `OverviewTab`, `LivePulseTicker` |
| Environment variables | `SCREAMING_SNAKE_CASE` | `COSMOS_ENDPOINT`, `TAB_MARKETPLACE_ENABLED` |
### API Endpoints
| Scope | Prefix | Auth |
|---|---|---|
| Public product API | `/api/` | `requireAuth` (platform JWT) |
| Internal operator tooling | `/internal/` | `requireAuth` — firewall-restrict in prod |
| Admin-only mutations | `/api/admin/` | `requireAuth` + `requireAdmin` |
| Health / observability | `/health`, `/metrics` | None — firewall-restrict in prod |
### Socket.IO Events (backend → client)
| Event | Payload type | Notes |
|---|---|---|
| `state` | `BotState` | Full state on connect |
| `symbol_update` | `{ symbol, data }` | Per-symbol signal/indicator update |
| `positions_update` | `Position[]` | Full position list replacement |
| `orders_update` | `Order[]` | Full order list replacement |
| `history_update` | `HistoryRow` | Single new closed trade |
| `new_alert` | `Alert` | Single new alert |
| `health_update` | `HealthSnapshot` | Loop health and trading control state |
| `account_snapshot` | `AccountSnapshot` | Exchange account balance snapshot |
| `order_failure` | `OrderFailureRecord` | Single order failure notification |
| `operational_event` | `OperationalEvent` | Structured operational log entry |
| `operational_event_cleared` | — | Signals log has been cleared |
---
## Feature Flag Conventions
- Feature flags are defined in `shared/feature-flags.ts` as TypeScript interfaces.
- Flag key constants (`BACKTEST_FLAG_KEYS`, `TAB_FLAG_KEYS`) are the single source of
truth for env var names — never hardcode the string elsewhere.
- Backend reads env vars via `config/index.ts`; web/mobile read via `GET /api/feature-flags`.
- Admin accounts bypass all feature flags — they always see everything.
- New flags default to **enabled** (opt-out model) unless gating a genuinely unreleased feature.
---
## Request Tracing Convention
Every HTTP request from web or mobile must include:
```
x-request-id: <createRequestId('surface-context')>
Authorization: Bearer <accessToken>
```
Backend echoes `x-request-id` in all responses. Use this header as the primary correlation
key when tracing a request across client logs and backend logs.
---
## Test / Verification Script Convention
Backend verification scripts follow this pattern:
```ts
// verify*.ts or test*.ts at backend/ root or backend/src/scripts/
import assert from 'node:assert/strict';
function main() {
// ... assertions ...
console.log('[PASS] Description of what passed.');
}
main();
```
- Exit with a non-zero code on `AssertionError` (Node.js default behaviour).
- Print `[PASS] ...` on success; never `console.log` progress in the happy path.
- Never connect to real infrastructure — use in-memory fixtures only.
- Wire into `package.json` scripts as `check:*` and into `npm run test` or `npm run lint`.