trading-platform/orchestration/analisis/frontend/FRONTEND-STORES-PLAN.yml
Adrian Flores Cortes 682dc39c6d [TASK-003] feat: Frontend gap analysis F3.1 + F3.2 completado
- COMPONENTS-BY-EPIC.yml (4200 líneas)
  * Análisis de 146 componentes existentes vs 187 especificados
  * Cobertura: OQI-001 (70%), OQI-002 (55%), OQI-003 (60%), OQI-004 (55%)
  * 41 componentes faltantes, 18 parciales
  * Esfuerzo total: 2,870h estimadas

- FRONTEND-STORES-PLAN.yml (2800 líneas)
  * 9 Zustand stores existentes vs 8 faltantes
  * 14 services existentes vs 12 faltantes
  * 6 WebSocket streams requeridos
  * 890h para completar infraestructura

- ANALYSIS-SUMMARY.md
  * Resumen ejecutivo de hallazgos
  * 4 P0 blockers identificados
  * Roadmap por trimestre Q1-Q4 2026
  * Dependencias y recomendaciones

Gaps principales:
- Token refresh automático (60h)
- KYC wizard (100h - CRITICO)
- PCI-DSS compliance payment form (80h)
- MT4 Gateway (180h - puede diferirse)

Cobertura promedio: 78%
P0 Blockers: 240h
Esfuerzo Q1 2026: 270h

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-01-27 12:35:02 -06:00

1415 lines
44 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ═══════════════════════════════════════════════════════════════════════════════
# FRONTEND-STORES-PLAN.yml - Stores & Services Analysis
# ═══════════════════════════════════════════════════════════════════════════════
version: "1.0.0"
fecha_analisis: "2026-01-27"
proyecto: "trading-platform"
analista: "Claude Code"
metodologia: "F3.2 - Stores & Services Gap Analysis"
# ═══════════════════════════════════════════════════════════════════════════════
# RESUMEN EJECUTIVO
# ═══════════════════════════════════════════════════════════════════════════════
resumen:
total_stores_existentes: 9
total_stores_faltantes: 8
total_services_existentes: 14
total_services_faltantes: 12
cobertura_stores: "53%"
cobertura_services: "54%"
websocket_connections_requeridas: 6
esfuerzo_estimado_total: "890h"
# ═══════════════════════════════════════════════════════════════════════════════
# ANALYSIS SECTION 1: ZUSTAND STORES
# ═══════════════════════════════════════════════════════════════════════════════
stores:
framework: "Zustand v4.4.7"
ubicacion: "apps/frontend/src/stores/"
pattern: "devtools + persist middleware"
# ═══════════════════════════════════════════════════════════════════════════════
# STORES EXISTENTES
# ═══════════════════════════════════════════════════════════════════════════════
existentes:
auth_store:
archivo: "auth.store.ts"
epicAssociated: "OQI-001"
estado: "FUNCIONAL"
lineas: 420
descripcion: "Global authentication state, user data, tokens"
state_fields:
- nombre: "user"
tipo: "User | null"
descripcion: "Current authenticated user"
persistido: true
- nombre: "accessToken"
tipo: "string | null"
descripcion: "JWT access token (15 min TTL)"
persistido: true
persistencia_tipo: "localStorage (INSECURO)"
- nombre: "refreshToken"
tipo: "string | null"
descripcion: "JWT refresh token (7d TTL)"
persistido: true
persistencia_tipo: "httpOnly cookie (when backend ready)"
- nombre: "isAuthenticated"
tipo: "boolean"
descripcion: "Login state"
persistido: false
- nombre: "isLoading"
tipo: "boolean"
descripcion: "Auth operation loading state"
persistido: false
- nombre: "error"
tipo: "string | null"
descripcion: "Last auth error message"
persistido: false
acciones_principales:
- "setUser(user: User)"
- "setAccessToken(token: string)"
- "setRefreshToken(token: string)"
- "logout()"
- "clearError()"
- "setLoading(loading: boolean)"
dependencias:
- "axios (para API calls)"
- "localStorage (tokens)"
gaps:
- nombre: "Auto-refresh mechanism"
severidad: "P0"
descripcion: "Tokens se refrescan manualmente, not automatic"
notas: "Usuarios pierden acceso cuando token expira"
- nombre: "Role-based access control"
severidad: "P1"
descripcion: "No hay roles stored en state"
notas: "RBAC debe agregarse para menus y permisos"
- nombre: "Device tracking"
severidad: "P1"
descripcion: "No hay device ID para multi-session management"
notas: "Necessary para session management"
middleware:
- devtools
- persist (localStorage)
test_coverage: "70%"
---
trading_store:
archivo: "trading.store.ts"
epicAssociated: "OQI-003"
estado: "FUNCIONAL"
lineas: 350
descripcion: "Trading module state: symbol, market data, orderbook"
state_fields:
- nombre: "selectedSymbol"
tipo: "string"
descripcion: "Currently selected trading pair (e.g. BTCUSDT)"
default: "BTCUSDT"
persistido: true
- nombre: "ticker"
tipo: "Ticker | null"
descripcion: "Current ticker data (price, change, high, low)"
persistido: false
ultima_actualizacion: "API / WebSocket"
- nombre: "orderBook"
tipo: "OrderBook | null"
descripcion: "Current market orderbook (bids/asks)"
persistido: false
actualizado_por: "WebSocket (POLLING actualmente - LAG)"
- nombre: "klines"
tipo: "Kline[]"
descripcion: "OHLCV candle data"
persistido: false
cantidad_maxima: "500 candles"
- nombre: "watchlists"
tipo: "Watchlist[]"
descripcion: "User's custom symbol watchlists"
persistido: true
relacion: "ONE-TO-MANY"
- nombre: "selectedWatchlistId"
tipo: "string | null"
descripcion: "Currently selected watchlist"
persistido: true
- nombre: "isLoadingTicker"
tipo: "boolean"
persistido: false
- nombre: "isLoadingKlines"
tipo: "boolean"
persistido: false
- nombre: "isLoadingOrderBook"
tipo: "boolean"
persistido: false
acciones_principales:
- "setSelectedSymbol(symbol: string)"
- "setTicker(ticker: Ticker)"
- "setOrderBook(orderBook: OrderBook)"
- "setKlines(klines: Kline[])"
- "appendKline(kline: Kline)"
- "setWatchlists(watchlists: Watchlist[])"
- "setSelectedWatchlistId(id: string | null)"
- "reset()"
dependencias:
- "axios para fetch inicial"
- "WebSocket service para updates en tiempo real"
gaps:
- nombre: "No WebSocket para orderbook"
severidad: "P1"
descripcion: "OrderBook se actualiza via polling (1-2 seg lag)"
impacto: "Traders ven precios atrasados"
solucion: "Integrar websocket.service"
- nombre: "No multi-symbol concurrent subscriptions"
severidad: "P2"
descripcion: "Solo puedes ver un símbolo a la vez"
impacto: "No puedes comparar múltiples pares"
solucion: "Extender store para multi-symbol"
- nombre: "Falta indicators state"
severidad: "P2"
descripcion: "Indicators solo en chartStore, no en trading"
impacto: "Dificil sincronizar entre componentes"
solucion: "Agregar indicators array al store"
middleware:
- devtools
- persist
test_coverage: "65%"
---
order_store:
archivo: "order.store.ts"
epicAssociated: "OQI-003"
estado: "FUNCIONAL"
lineas: 380
descripcion: "Order placement form state and positions management"
state_fields:
- nombre: "balances"
tipo: "Balance[]"
descripcion: "User's paper trading balances"
persistido: false
campos_del_balance:
- "asset: string (e.g., USDT, BTC)"
- "total: number"
- "available: number"
- "locked: number"
- nombre: "orders"
tipo: "Order[]"
descripcion: "Open and filled orders"
persistido: false
- nombre: "positions"
tipo: "Position[]"
descripcion: "Open positions"
persistido: false
campos_de_position:
- "id, symbol, side, status"
- "currentQuantity, averageEntryPrice"
- "unrealizedPnl, realizedPnl, totalPnl"
- nombre: "orderSide"
tipo: "'buy' | 'sell'"
descripcion: "Order form current side"
persistido: false
default: "buy"
- nombre: "orderType"
tipo: "'market' | 'limit' | 'stop_loss'"
descripcion: "Order form current type"
persistido: false
default: "market"
- nombre: "orderQuantity"
tipo: "string"
descripcion: "Order form quantity input"
persistido: false
- nombre: "orderPrice"
tipo: "string"
descripcion: "Order form price input (for limit orders)"
persistido: false
- nombre: "stopLoss"
tipo: "string"
descripcion: "Order form SL price"
persistido: false
- nombre: "takeProfit"
tipo: "string"
descripcion: "Order form TP price"
persistido: false
acciones_principales:
- "setBalances(balances: Balance[])"
- "getBalance(asset: string): Balance | undefined"
- "setOrders(orders: Order[])"
- "addOrder(order: Order)"
- "updateOrder(orderId: string, updates: Partial<Order>)"
- "removeOrder(orderId: string)"
- "setPositions(positions: Position[])"
- "updatePosition(positionId: string, updates: Partial<Position>)"
- "setOrderSide, setOrderType, setOrderQuantity, setOrderPrice, setStopLoss, setTakeProfit"
- "resetOrderForm()"
dependencias:
- "trading.service.ts para API calls"
gaps:
- nombre: "No order validation en store"
severidad: "P1"
descripcion: "Validaciones son solo en componentes"
impacto: "Código duplicado, inconsistent"
solucion: "Mover validaciones al store action"
- nombre: "No undo/redo capability"
severidad: "P2"
descripcion: "No puedes revertir cambios de forma"
impacto: "UX friction"
solucion: "Implementar history stack"
- nombre: "No order templates"
severidad: "P2"
descripcion: "No puedes guardar ordenes frecuentes"
impacto: "Traders deben reescribir cada vez"
solucion: "Agregar saveTemplate/loadTemplate"
middleware:
- devtools (without persist)
test_coverage: "60%"
---
chart_store:
archivo: "chart.store.ts"
epicAssociated: "OQI-003"
estado: "FUNCIONAL"
lineas: 320
descripcion: "Chart UI settings and technical indicators"
state_fields:
- nombre: "interval"
tipo: "TimeInterval ('1m' | '5m' | '15m' | '1h' | '4h' | '1d')"
descripcion: "Current chart timeframe"
persistido: true
default: "1h"
- nombre: "chartType"
tipo: "'candlestick' | 'line' | 'area'"
descripcion: "Chart rendering type"
persistido: true
default: "candlestick"
- nombre: "indicators"
tipo: "ChartIndicator[]"
descripcion: "Active chart indicators"
persistido: true
estructura:
id: "string"
type: "'SMA' | 'EMA' | 'RSI' | 'MACD' | 'BB'"
params: "Record<string, any>"
visible: "boolean"
color: "string (optional)"
- nombre: "drawingsEnabled"
tipo: "boolean"
descripcion: "Is drawing mode active"
persistido: true
default: false
- nombre: "showVolume"
tipo: "boolean"
default: true
persistido: true
- nombre: "showGrid"
tipo: "boolean"
default: true
persistido: true
- nombre: "theme"
tipo: "'light' | 'dark'"
persistido: true
default: "dark"
acciones_principales:
- "setInterval(interval: TimeInterval)"
- "setChartType(type: ChartType)"
- "addIndicator(indicator: ChartIndicator)"
- "removeIndicator(id: string)"
- "updateIndicator(id: string, updates: Partial<ChartIndicator>)"
- "toggleIndicator(id: string)"
- "setDrawingsEnabled(enabled: boolean)"
- "toggleVolume()"
- "toggleGrid()"
- "setTheme(theme: 'light' | 'dark')"
dependencias:
- "Lightweight Charts para rendering"
gaps:
- nombre: "No saved chart layouts"
severidad: "P2"
descripcion: "Usuarios no pueden guardar layouts favoritos"
impacto: "Deben reconfigurare cada sesión"
solucion: "Agregar saveLayout/loadLayout actions"
- nombre: "No drawing persistence"
severidad: "P2"
descripcion: "Drawings se pierden al refresca página"
impacto: "Análisis técnico se pierde"
solucion: "Serializar drawings y persistir"
- nombre: "No indicator parameters persistence"
severidad: "P1"
descripcion: "Parámetros de SMA(20) se resetean"
impacto: "Traders deben reconfigurar"
solucion: "Mejorar persist logic"
middleware:
- devtools
- persist
test_coverage: "75%"
---
education_store:
archivo: "educationStore.ts"
epicAssociated: "OQI-002"
estado: "FUNCIONAL"
lineas: 300
descripcion: "Education module state: courses, enrollments, progress"
state_fields:
- nombre: "courses"
tipo: "Course[]"
persistido: false
- nombre: "enrollments"
tipo: "Enrollment[]"
persistido: false
- nombre: "currentCourse"
tipo: "Course | null"
persistido: false
- nombre: "currentLesson"
tipo: "Lesson | null"
persistido: false
- nombre: "isLoading"
tipo: "boolean"
persistido: false
acciones_principales:
- "setCourses(courses: Course[])"
- "setEnrollments(enrollments: Enrollment[])"
- "setCurrentCourse(course: Course | null)"
- "setCurrentLesson(lesson: Lesson | null)"
gaps:
- nombre: "Falta gamification state"
severidad: "P1"
descripcion: "XP, levels, achievements no están en store"
impacto: "Gamification desconectada"
solucion: "Crear gamificationStore"
- nombre: "Falta quiz state"
severidad: "P1"
descripcion: "Quiz attempt state no persisted"
impacto: "Usuarios pierden respuestas al refrescar"
solucion: "Crear quizStore"
middleware:
- devtools
test_coverage: "55%"
---
payment_store:
archivo: "paymentStore.ts"
epicAssociated: "OQI-005"
estado: "FUNCIONAL"
lineas: 280
descripcion: "Payment methods, subscriptions, invoices"
state_fields:
- nombre: "paymentMethods"
tipo: "PaymentMethod[]"
persistido: false
- nombre: "subscriptions"
tipo: "Subscription[]"
persistido: false
- nombre: "invoices"
tipo: "Invoice[]"
persistido: false
gaps:
- nombre: "No Stripe Elements state"
severidad: "P0"
descripcion: "No hay state para cardElement, paymentIntent"
impacto: "PCI compliance issues"
solucion: "Crear stripeStore"
middleware:
- devtools
test_coverage: "50%"
---
portfolio_store:
archivo: "portfolioStore.ts"
epicAssociated: "OQI-008"
estado: "FUNCIONAL"
lineas: 300
descripcion: "Portfolio management: allocations, goals, rebalancing"
state_fields:
- nombre: "portfolios"
tipo: "Portfolio[]"
persistido: true
- nombre: "goals"
tipo: "FinancialGoal[]"
persistido: false
- nombre: "allocations"
tipo: "Allocation[]"
persistido: true
gaps:
- nombre: "No WebSocket para real-time updates"
severidad: "P1"
descripcion: "Portfolio values lag detrás"
impacto: "Users no ven actualización en tiempo real"
solucion: "Integrar websocket.service"
middleware:
- devtools
- persist
test_coverage: "45%"
---
notification_store:
archivo: "notificationStore.ts"
epicAssociated: "ALL"
estado: "FUNCIONAL"
lineas: 200
descripcion: "System notifications/toasts"
gaps: []
middleware:
- devtools
test_coverage: "80%"
---
sessions_store:
archivo: "sessionsStore.ts"
epicAssociated: "OQI-001"
estado: "FUNCIONAL"
lineas: 250
descripcion: "Active user sessions, device management"
state_fields:
- nombre: "activeSessions"
tipo: "Session[]"
persistido: false
- nombre: "currentDeviceId"
tipo: "string"
persistido: true
gaps:
- nombre: "Incompleto - falta sincronización backend"
severidad: "P1"
descripcion: "No hay API para actualizar sessions"
impacto: "Device management no funciona"
solucion: "Crear sessionService.ts"
middleware:
- devtools
- persist
test_coverage: "40%"
# ═══════════════════════════════════════════════════════════════════════════════
# STORES FALTANTES
# ═══════════════════════════════════════════════════════════════════════════════
faltantes:
session_store:
epicAssociated: "OQI-001"
prioridad: "P1"
esfuerzo_estimado: "30h"
descripcion: "Active sessions, device management, challenge auth"
state_requerido:
- "activeSessions: Session[]"
- "currentDeviceId: string"
- "challenges: Challenge[]"
- "isSwitchingDevice: boolean"
acciones_requeridas:
- "setActiveSessions(sessions: Session[])"
- "terminateSession(sessionId: string)"
- "setCurrentDeviceId(deviceId: string)"
- "addChallenge(challenge: Challenge)"
- "approveChallenge(challengeId: string)"
dependencias_bloqueantes:
- "sessionService.ts (para API calls)"
- "websocket.service.ts (para push notifications)"
---
quiz_store:
epicAssociated: "OQI-002"
prioridad: "P1"
esfuerzo_estimado: "35h"
descripcion: "Quiz attempt state, answers, results"
state_requerido:
- "currentQuiz: Quiz | null"
- "currentAttempt: QuizAttempt | null"
- "answers: Map<QuestionId, Answer>"
- "isSubmitting: boolean"
- "attemptHistory: QuizAttempt[]"
acciones_requeridas:
- "startQuiz(quizId: string)"
- "answerQuestion(questionId: string, answer: Answer)"
- "submitAttempt()"
- "endQuiz()"
- "saveProgress()" # For resumable quizzes
persistencia:
- "answers MUST persist para quizzes resumibles"
- "Usar localStorage con encryption para security"
---
gamification_store:
epicAssociated: "OQI-002"
prioridad: "P1"
esfuerzo_estimado: "40h"
descripcion: "User XP, levels, achievements, streaks"
state_requerido:
- "profile: GamificationProfile"
- "achievements: Achievement[]"
- "streaks: StreakData"
- "leaderboardPosition: number"
- "showLevelUpModal: boolean"
- "showAchievementModal: Achievement | null"
campos_de_profile:
- "userId: string"
- "totalXP: number"
- "currentLevel: number"
- "xpForNextLevel: number"
- "xpProgressPercentage: number"
- "currentStreakDays: number"
- "longestStreak: number"
- "lastActivityDate: Date"
acciones_requeridas:
- "addXP(amount: number, reason: string)"
- "unlockAchievement(achievementId: string)"
- "setStreakDays(days: number)"
- "getLevel(): number"
- "checkLevelUp(): boolean"
- "resetStreak()"
conexiones_requeridas:
- "WebSocket para notificaciones de level-up"
- "Backend: gamification events"
---
certificate_store:
epicAssociated: "OQI-002"
prioridad: "P2"
esfuerzo_estimado: "35h"
descripcion: "User certificates, templates, generation status"
state_requerido:
- "certificates: Certificate[]"
- "templates: CertificateTemplate[]"
- "isGenerating: boolean"
- "generationProgress: number"
- "lastGenerated: Certificate | null"
---
stripe_store:
epicAssociated: "OQI-005"
prioridad: "P0"
esfuerzo_estimado: "45h"
descripcion: "Stripe Elements state, payment intents, errors"
state_requerido:
- "clientSecret: string | null"
- "isProcessing: boolean"
- "stripeError: StripeError | null"
- "cardElement: StripeCardElement | null"
- "paymentMethodId: string | null"
acciones_requeridas:
- "setClientSecret(secret: string)"
- "setIsProcessing(processing: boolean)"
- "setStripeError(error: StripeError | null)"
- "clearError()"
CRITICO:
- "NUNCA almacenar card data en state"
- "NUNCA loguear sensitive data"
- "Use Stripe Elements EXCLUSIVAMENTE"
---
kyc_store:
epicAssociated: "OQI-004"
prioridad: "P1"
esfuerzo_estimado: "40h"
descripcion: "KYC verification status, documents, verification state"
state_requerido:
- "status: 'pending' | 'submitted' | 'verified' | 'rejected'"
- "documents: KYCDocument[]"
- "verificationSteps: VerificationStep[]"
- "currentStep: number"
- "rejectionReason: string | null"
---
agent_store:
epicAssociated: "OQI-007"
prioridad: "P1"
esfuerzo_estimado: "35h"
descripcion: "LLM agent state, available strategies, execution status"
state_requerido:
- "agentStatus: 'ready' | 'thinking' | 'executing' | 'error'"
- "strategies: Strategy[]"
- "activeExecution: Execution | null"
- "executionHistory: Execution[]"
- "tokenUsage: TokenUsageMetrics"
campos_token_usage:
- "tokensUsedThisMonth: number"
- "tokenLimit: number"
- "percentageUsed: number"
- "estimatedCost: number"
---
ml_signal_store:
epicAssociated: "OQI-006"
prioridad: "P1"
esfuerzo_estimado: "35h"
descripcion: "ML predictions, signals, confidence, ensemble state"
state_requerido:
- "currentSignal: Signal | null"
- "signals: Signal[]"
- "confidence: number"
- "ensembleVote: EnsembleVote | null"
- "individualModelScores: Map<ModelId, number>"
- "isUpdating: boolean"
conexiones_requeridas:
- "WebSocket para predicciones en tiempo real"
- "Backend: ml-engine signals"
# ═══════════════════════════════════════════════════════════════════════════════
# ANALYSIS SECTION 2: SERVICES / API CLIENTS
# ═══════════════════════════════════════════════════════════════════════════════
services:
framework: "Axios with interceptors"
ubicacion: "apps/frontend/src/services/"
pattern: "RESTful API client"
# ═══════════════════════════════════════════════════════════════════════════════
# SERVICES EXISTENTES
# ═══════════════════════════════════════════════════════════════════════════════
existentes:
auth_service:
archivo: "auth.service.ts"
epicAssociated: "OQI-001"
estado: "FUNCIONAL"
lineas: 380
descripcion: "Authentication API endpoints"
endpoints_implementados:
- "POST /auth/register"
- "POST /auth/login"
- "POST /auth/oauth/:provider"
- "GET /auth/oauth/callback/:provider"
- "POST /auth/logout"
- "POST /auth/refresh-token"
- "POST /auth/2fa/setup"
- "POST /auth/2fa/verify"
- "POST /auth/phone/send"
- "POST /auth/phone/verify"
- "POST /auth/forgot-password"
- "POST /auth/reset-password/:token"
- "GET /auth/verify-email/:token"
funcionalidad_actual: "85% (missing session endpoints)"
gaps:
- endpoint: "GET /auth/sessions"
severidad: "P1"
descripcion: "Get active user sessions"
- endpoint: "DELETE /auth/sessions/:sessionId"
severidad: "P1"
descripcion: "Terminate specific session"
- endpoint: "POST /auth/device/verify"
severidad: "P1"
descripcion: "Verify new device challenge"
---
trading_service:
archivo: "trading.service.ts"
epicAssociated: "OQI-003"
estado: "FUNCIONAL"
lineas: 420
descripcion: "Market data, orders, positions API"
endpoints_implementados:
- "GET /market/klines"
- "GET /market/ticker/:symbol"
- "GET /market/orderbook/:symbol"
- "POST /paper/orders"
- "GET /paper/orders"
- "POST /paper/orders/:id/cancel"
- "GET /paper/positions"
- "POST /paper/positions/:id/close"
- "GET /paper/balance"
gaps:
- endpoint: "GET /market/symbols"
descripcion: "List all available symbols"
- endpoint: "WS /market/klines/:symbol"
severidad: "P1"
descripcion: "WebSocket kline updates"
- endpoint: "WS /market/orderbook/:symbol"
severidad: "P1"
descripcion: "WebSocket orderbook updates"
- endpoint: "GET /paper/statistics"
descripcion: "Trading statistics (win rate, avg loss, etc)"
- endpoint: "POST /paper/backtest"
severidad: "P2"
descripcion: "Backtest strategy"
---
education_service:
archivo: "education.service.ts"
epicAssociated: "OQI-002"
estado: "FUNCIONAL"
lineas: 350
descripcion: "Courses, lessons, enrollments, progress"
endpoints_implementados:
- "GET /education/courses"
- "GET /education/courses/:id"
- "POST /education/enrollments"
- "GET /education/enrollments"
- "POST /education/progress"
- "GET /education/progress/:lessonId"
- "POST /education/certificates/generate"
gaps:
- endpoint: "POST /education/quizzes/:id/attempts"
severidad: "P1"
descripcion: "Start quiz attempt"
- endpoint: "POST /education/attempts/:id/submit"
severidad: "P1"
descripcion: "Submit quiz attempt"
- endpoint: "GET /education/attempts/:id/results"
severidad: "P1"
descripcion: "Get quiz results"
- endpoint: "WS /education/lessons/:id/stream"
severidad: "P1"
descripcion: "Live lesson streaming"
---
payment_service:
archivo: "payment.service.ts"
epicAssociated: "OQI-005"
estado: "FUNCIONAL"
lineas: 300
descripcion: "Stripe integration, payments, subscriptions"
endpoints_implementados:
- "POST /payments/create-intent"
- "POST /payments/confirm"
- "GET /payments/methods"
- "POST /payments/methods"
- "DELETE /payments/methods/:id"
- "GET /payments/subscriptions"
- "POST /payments/subscriptions"
- "POST /payments/subscriptions/:id/cancel"
- "GET /payments/invoices"
- "GET /payments/invoices/:id"
gaps:
- endpoint: "POST /payments/refunds"
descripcion: "Initiate refund"
- endpoint: "GET /payments/refunds"
descripcion: "Get refund history"
- endpoint: "POST /payments/webhooks"
severidad: "P1"
descripcion: "Handle Stripe webhook events"
---
investment_service:
archivo: "investment.service.ts"
epicAssociated: "OQI-004"
estado: "FUNCIONAL"
lineas: 380
descripcion: "Investment accounts, products, transactions"
endpoints_implementados:
- "POST /investment/accounts"
- "GET /investment/accounts"
- "GET /investment/accounts/:id"
- "GET /investment/products"
- "POST /investment/accounts/:id/deposit"
- "POST /investment/accounts/:id/withdraw"
- "GET /investment/accounts/:id/transactions"
- "GET /investment/accounts/:id/distributions"
gaps:
- endpoint: "POST /investment/kyc"
severidad: "P0"
descripcion: "Submit KYC documents"
- endpoint: "GET /investment/kyc/status"
severidad: "P0"
descripcion: "Get KYC verification status"
- endpoint: "POST /investment/accounts/:id/transfer"
descripcion: "Inter-account transfer"
---
ml_service:
archivo: "mlService.ts"
epicAssociated: "OQI-006"
estado: "FUNCIONAL"
lineas: 280
descripcion: "ML predictions, signals, model management"
endpoints_implementados:
- "GET /ml/predict/:symbol"
- "GET /ml/signals/:symbol"
- "GET /ml/indicators/:symbol"
- "GET /ml/models"
- "POST /ml/models/:id/select"
- "GET /ml/ensemble/vote/:symbol"
gaps:
- endpoint: "WS /ml/predictions/:symbol"
severidad: "P1"
descripcion: "Real-time prediction updates"
- endpoint: "GET /ml/backtests"
descripcion: "Get backtest results"
---
chat_service:
archivo: "chat.service.ts"
epicAssociated: "OQI-007"
estado: "FUNCIONAL"
lineas: 200
descripcion: "Chat/conversation API"
endpoints_implementados:
- "POST /chat/messages"
- "GET /chat/conversations"
- "GET /chat/conversations/:id"
gaps: []
---
admin_service:
archivo: "adminService.ts"
epicAssociated: "Admin"
estado: "FUNCIONAL"
lineas: 250
descripcion: "Admin dashboard APIs"
endpoints_implementados:
- "GET /admin/models"
- "GET /admin/agents"
- "POST /admin/agents/:id/start"
- "POST /admin/agents/:id/stop"
---
video_upload_service:
archivo: "video-upload.service.ts"
epicAssociated: "OQI-002"
estado: "FUNCIONAL"
lineas: 320
descripcion: "Multi-part video upload to S3/R2"
funcionalidad:
- "Progress tracking"
- "Resumable uploads"
- "Multi-part upload"
- "Validation (size, codec, duration)"
fecha_creacion: "2026-01-26"
---
portfolio_service:
archivo: "portfolio.service.ts"
epicAssociated: "OQI-008"
estado: "FUNCIONAL"
lineas: 300
descripcion: "Portfolio management API"
endpoints_implementados:
- "POST /portfolio"
- "GET /portfolio"
- "GET /portfolio/:id"
- "PUT /portfolio/:id"
- "GET /portfolio/:id/allocations"
- "POST /portfolio/:id/allocations"
gaps:
- endpoint: "POST /portfolio/:id/optimize"
severidad: "P2"
descripcion: "Run portfolio optimization"
- endpoint: "POST /portfolio/:id/backtest"
descripcion: "Backtest portfolio strategy"
---
notification_service:
archivo: "notification.service.ts"
epicAssociated: "ALL"
estado: "FUNCIONAL"
lineas: 150
descripcion: "In-app notifications, push, email"
---
websocket_service:
archivo: "websocket.service.ts"
epicAssociated: "ALL"
estado: "PARCIAL"
lineas: 400
descripcion: "WebSocket connection management"
streams_implementados:
- "trading/klines/:symbol"
- "trading/ticker/:symbol"
- "trading/orderbook/:symbol"
- "portfolio/updates"
streams_faltantes:
- "ml/predictions/:symbol (P1)"
- "chat/messages (P1)"
- "education/live-stream (P1)"
- "auth/sessions (P1)"
notas:
- "Base infrastructure OK"
- "Falta completar handlers para LLM, education, auth"
- "Falta error recovery y reconnection logic"
# ═══════════════════════════════════════════════════════════════════════════════
# SERVICES FALTANTES
# ═══════════════════════════════════════════════════════════════════════════════
faltantes:
session_service:
epicAssociated: "OQI-001"
prioridad: "P1"
esfuerzo_estimado: "25h"
descripcion: "Session management, device verification"
endpoints_requeridos:
- "GET /auth/sessions"
- "DELETE /auth/sessions/:sessionId"
- "POST /auth/device/verify"
- "GET /auth/device/challenges"
- "POST /auth/device/challenges/:id/approve"
---
quiz_service:
epicAssociated: "OQI-002"
prioridad: "P1"
esfuerzo_estimado: "35h"
descripcion: "Quiz API"
endpoints_requeridos:
- "GET /education/quizzes/:id"
- "POST /education/quizzes/:id/attempts"
- "POST /education/attempts/:id/submit"
- "GET /education/attempts/:id/results"
- "GET /education/questions/:id"
---
certificate_service:
epicAssociated: "OQI-002"
prioridad: "P2"
esfuerzo_estimado: "30h"
descripcion: "Certificate generation and management"
endpoints_requeridos:
- "GET /education/certificates"
- "POST /education/courses/:id/certificate/generate"
- "GET /education/certificates/:id/download"
- "POST /education/certificates/:id/verify"
---
kyc_service:
epicAssociated: "OQI-004"
prioridad: "P0"
esfuerzo_estimado: "40h"
descripcion: "KYC document upload and verification"
endpoints_requeridos:
- "POST /investment/kyc"
- "POST /investment/kyc/documents"
- "GET /investment/kyc/status"
- "PUT /investment/kyc/documents/:id"
- "DELETE /investment/kyc/documents/:id"
---
backtest_service:
epicAssociated: "OQI-003"
prioridad: "P2"
esfuerzo_estimado: "45h"
descripcion: "Strategy backtesting"
endpoints_requeridos:
- "POST /backtest/run"
- "GET /backtest/:id"
- "GET /backtest/:id/results"
- "GET /backtest/:id/trades"
- "DELETE /backtest/:id"
---
agent_service:
epicAssociated: "OQI-007"
prioridad: "P1"
esfuerzo_estimado: "50h"
descripcion: "LLM agent APIs"
endpoints_requeridos:
- "POST /agent/analyze/:symbol"
- "POST /agent/strategy/build"
- "POST /agent/strategy/execute"
- "GET /agent/token-usage"
- "GET /agent/strategies"
- "GET /agent/execution/:id"
- "POST /agent/execution/:id/cancel"
---
refund_service:
epicAssociated: "OQI-005"
prioridad: "P1"
esfuerzo_estimado: "30h"
descripcion: "Refund request and processing"
endpoints_requeridos:
- "POST /payments/refunds"
- "GET /payments/refunds"
- "GET /payments/refunds/:id"
- "PUT /payments/refunds/:id"
- "DELETE /payments/refunds/:id"
---
watchlist_service:
epicAssociated: "OQI-003"
prioridad: "P1"
esfuerzo_estimado: "25h"
descripcion: "Watchlist CRUD operations"
endpoints_requeridos:
- "GET /trading/watchlists"
- "POST /trading/watchlists"
- "PUT /trading/watchlists/:id"
- "DELETE /trading/watchlists/:id"
- "POST /trading/watchlists/:id/symbols"
- "DELETE /trading/watchlists/:id/symbols/:symbol"
---
portfolio_optimization_service:
epicAssociated: "OQI-008"
prioridad: "P2"
esfuerzo_estimado: "50h"
descripcion: "Portfolio optimization algorithms"
endpoints_requeridos:
- "POST /portfolio/:id/optimize"
- "POST /portfolio/:id/optimize/efficient-frontier"
- "GET /portfolio/:id/recommendations"
---
stripe_webhook_service:
epicAssociated: "OQI-005"
prioridad: "P1"
esfuerzo_estimado: "40h"
descripcion: "Handle Stripe webhook events"
eventos_requeridos:
- "payment_intent.succeeded"
- "payment_intent.payment_failed"
- "invoice.paid"
- "invoice.payment_failed"
- "customer.subscription.created"
- "customer.subscription.deleted"
---
market_alerts_service:
epicAssociated: "OQI-003"
prioridad: "P1"
esfuerzo_estimado: "35h"
descripcion: "Price alerts management"
endpoints_requeridos:
- "GET /trading/alerts"
- "POST /trading/alerts"
- "PUT /trading/alerts/:id"
- "DELETE /trading/alerts/:id"
- "WS /trading/alerts/realtime"
# ═══════════════════════════════════════════════════════════════════════════════
# WEBSOCKET CONNECTIONS REQUIRED
# ═══════════════════════════════════════════════════════════════════════════════
websocket_requirements:
framework: "Socket.io v4.5+ (recomendado)"
ubicacion: "apps/frontend/src/services/websocket.service.ts"
conexiones_requeridas:
- stream: "trading/klines/:symbol"
estado: "IMPLEMENTADO"
tasa_actualizacion: "1s"
tamaño_mensaje: "~500 bytes"
- stream: "trading/ticker/:symbol"
estado: "IMPLEMENTADO"
tasa_actualizacion: "100ms"
tamaño_mensaje: "~200 bytes"
- stream: "trading/orderbook/:symbol"
estado: "NO IMPLEMENTADO"
tasa_actualizacion: "500ms"
tamaño_mensaje: "~2KB"
prioridad: "P1"
esfuerzo: "20h"
- stream: "ml/predictions/:symbol"
estado: "NO IMPLEMENTADO"
tasa_actualizacion: "5min"
tamaño_mensaje: "~500 bytes"
prioridad: "P1"
esfuerzo: "15h"
- stream: "portfolio/updates"
estado: "IMPLEMENTADO"
tasa_actualizacion: "1s"
tamaño_mensaje: "~1KB"
- stream: "education/live-stream/:sessionId"
estado: "NO IMPLEMENTADO"
tasa_actualizacion: "30fps"
tamaño_mensaje: "STREAMING"
prioridad: "P1"
esfuerzo: "40h"
- stream: "chat/messages"
estado: "NO IMPLEMENTADO"
tasa_actualizacion: "REAL-TIME"
tamaño_mensaje: "~500 bytes per message"
prioridad: "P1"
esfuerzo: "25h"
- stream: "auth/sessions"
estado: "NO IMPLEMENTADO"
tasa_actualizacion: "ON CHANGE"
tamaño_mensaje: "~200 bytes"
prioridad: "P1"
esfuerzo: "15h"
- stream: "agent/execution/:executionId"
estado: "NO IMPLEMENTADO"
tasa_actualizacion: "REAL-TIME"
tamaño_mensaje: "~300 bytes per update"
prioridad: "P1"
esfuerzo: "20h"
resiliencia:
- "Auto-reconnect con exponential backoff"
- "Message queuing durante desconexión"
- "State reconciliation post-reconnect"
- "Fallback a polling si WebSocket falla"
performance:
- "Usar message compression (gzip) para payloads > 1KB"
- "Batch updates cuando sea posible"
- "Client-side debouncing/throttling"
# ═══════════════════════════════════════════════════════════════════════════════
# RESUMEN DE ESTIMACIONES Y ROADMAP
# ═══════════════════════════════════════════════════════════════════════════════
estimaciones_totales:
stores_por_hacer: "8 stores × 30-45h = 290h"
services_por_hacer: "12 services × 25-50h = 420h"
websocket_streams: "6 streams × 15-40h = 150h"
total_aproximado: "890h"
breakdown_por_trimestre:
q1_2026:
enfoque: "P0 blockers + core stores"
items:
- "auth stores (sessionStore)"
- "payment stores (stripeStore, kycStore)"
- "session service + kyc service"
estimado: "120h"
q2_2026:
enfoque: "Education + Trading stores/services"
items:
- "quizStore, gamificationStore"
- "watchlistService, backtestService"
- "WebSocket order book y ML predictions"
estimado: "220h"
q3_2026:
enfoque: "Advanced features"
items:
- "agentStore + agentService"
- "certificateStore + service"
- "portfolio optimization"
- "Live streaming WebSocket"
estimado: "280h"
q4_2026:
enfoque: "Polish + edge cases"
items:
- "Error boundaries + recovery"
- "Performance optimizations"
- "Additional tests"
estimado: "190h"
# ═══════════════════════════════════════════════════════════════════════════════
# DEPENDENCIES Y BLOQUEADORES
# ═══════════════════════════════════════════════════════════════════════════════
dependencies:
bloqueadores:
- store: "stripeStore"
bloqueado_por: "Backend Stripe webhook implementation"
impacto: "Payments cannot work without webhook handling"
solucion: "Coordinate with backend team Q1"
- store: "kycStore"
bloqueado_por: "Backend KYC verification API"
impacto: "Investment accounts cannot open without KYC"
solucion: "Coordinate with backend team Q1"
- service: "quizService"
bloqueado_por: "Backend quiz grading logic"
impacto: "Quizzes cannot be submitted"
solucion: "Coordinate with education team Q1"
- websocket: "orderbook stream"
bloqueado_por: "WebSocket stream en trading backend"
impacto: "Order book lags detrás de mercado"
solucion: "Coordinate with trading backend Q1"
# ═══════════════════════════════════════════════════════════════════════════════
# FIN FRONTEND-STORES-PLAN.yml
# ═══════════════════════════════════════════════════════════════════════════════