SuperSkin Platform Architecture
Document Purpose
This document defines the architecture and design required to evolve SuperSkin from 5 independent microservices into an integrated intelligent betting platform that supports the complex user scenarios defined in USER_FLOWS.md.
Current State vs Target State
┌─────────────────────────────────────────────────────────────────────────────┐
│ CURRENT STATE │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Price Feed │ │ Cash Out │ │ AI Value │ │ AI Chat │ │
│ │ Aggregator │ │ Calculator │ │ Detection │ │ Assistant │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │ │
│ └────────────────┴─────────────────┴─────────────────┘ │
│ │ │
│ No User Context │
│ No Cross-Service State │
│ No Alerts/Notifications │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ TARGET STATE │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ API Gateway (Auth + Routing) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │ │ │ │ │
│ ┌──────▼──────┐ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ ┌───────▼─────┐ │
│ │ Price Feed │ │ Cash Out │ │ AI Value │ │ AI Chat │ │ Trading │ │
│ │ Aggregator │ │ Calculator│ │ Detection │ │ Assistant │ │ Charts │ │
│ └──────┬──────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └───────┬─────┘ │
│ │ │ │ │ │ │
│ ┌──────▼──────────────▼──────────────▼──────────────▼──────────────▼─────┐ │
│ │ Shared Service Layer │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
│ │ │ User │ │ Watchlist & │ │ Position │ │ Strategy & │ │ │
│ │ │ Context │ │ Alerts │ │ Tracker │ │ Rules Engine │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────▼─────────────┐ │
│ │ smartbets-protocol │ │
│ │ (Backend Platform) │ │
│ └───────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Architecture Principles
- User Context Everywhere - Every service call includes user identity
- Event-Driven - Services communicate via events for real-time updates
- Graceful Degradation - Features work standalone if dependencies fail
- Single Source of Truth - Backend platform owns user data, SuperSkin caches
- Security by Design - JWT auth, RLS policies, encrypted PII
Document Structure
This architecture is organized into the following sections:
- System Components - All services and their responsibilities
- Data Architecture - Schemas, storage, and data flows
- API Contracts - Service interfaces and protocols
- Feature Specifications - Detailed designs per feature
- Infrastructure - Deployment, scaling, monitoring
- Implementation Phases - Build order and dependencies
1. System Components
1.1 Existing Services (To Be Enhanced)
| Service | Current Role | Enhancement Needed |
|---|---|---|
| Price Feed Aggregator | Aggregate multi-book prices | Add user preferences, favorites |
| Cash Out Calculator | Calculate cash out values | Connect to user positions |
| AI Value Detection | Detect value opportunities | Track user performance |
| AI Chat Assistant | Conversational AI | Full user context, history |
| Trading Charts | OHLC chart data | Watchlists, portfolio overlay |
1.2 New Shared Services
| Service | Responsibility | Key Features |
|---|---|---|
| User Context Service | User identity & preferences | JWT validation, preference cache |
| Watchlist Service | Watchlist & favorite tracking | CRUD, sharing, notifications |
| Alert Engine | Price & event monitoring | Rule evaluation, triggers |
| Position Tracker | Live position management | Sync from backend, P&L |
| Strategy Engine | Rule-based constraints | Staking rules, limits |
| Notification Hub | Multi-channel delivery | Push, email, SMS routing |
1.3 External Dependencies
| System | Integration Type | Purpose |
|---|---|---|
| smartbets-protocol | REST API | User data, betting history, positions |
| Supabase | PostgreSQL + Realtime | Persistent storage, real-time sync |
| Redis | Cache + Pub/Sub | Session cache, event streaming |
| Grok API | LLM Provider | AI conversations, search |
2. Data Architecture
2.1 User Context Schema
-- Cached user preferences in SuperSkin (source: backend)
CREATE TABLE user_context (
user_id UUID PRIMARY KEY,
email TEXT,
display_name TEXT,
preferences JSONB DEFAULT '{}',
-- Cached from backend
total_bets INTEGER DEFAULT 0,
win_rate DECIMAL(5,4),
total_pnl DECIMAL(12,2),
favorite_sports TEXT[],
favorite_markets TEXT[],
-- Timestamps
last_synced_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Example preferences JSONB:
-- {
-- "default_stake": 100,
-- "odds_format": "decimal",
-- "timezone": "Asia/Kolkata",
-- "risk_level": "medium",
-- "auto_refresh": true,
-- "notification_channels": ["push", "email"]
-- }
2.2 Watchlist Schema
CREATE TABLE watchlists (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES user_context(user_id),
name TEXT NOT NULL,
description TEXT,
is_default BOOLEAN DEFAULT false,
is_shared BOOLEAN DEFAULT false,
share_code TEXT UNIQUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE watchlist_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE,
-- What we're watching
item_type TEXT NOT NULL, -- 'selection', 'event', 'market', 'team'
item_id TEXT NOT NULL,
item_name TEXT NOT NULL,
-- Display data (cached)
metadata JSONB DEFAULT '{}',
-- Tracking
added_at TIMESTAMPTZ DEFAULT NOW(),
last_price DECIMAL(10,4),
price_at_add DECIMAL(10,4),
notes TEXT,
UNIQUE(watchlist_id, item_type, item_id)
);
CREATE INDEX idx_watchlist_items_user ON watchlist_items(watchlist_id);
2.3 Alert Rules Schema
CREATE TYPE alert_status AS ENUM ('active', 'triggered', 'expired', 'disabled');
CREATE TYPE alert_type AS ENUM (
'price_above', 'price_below', 'price_change_pct',
'steam_move', 'value_signal', 'arbitrage',
'match_start', 'goal_scored', 'position_pnl'
);
CREATE TABLE alert_rules (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES user_context(user_id),
-- What to monitor
alert_type alert_type NOT NULL,
target_type TEXT NOT NULL, -- 'selection', 'event', 'position'
target_id TEXT NOT NULL,
target_name TEXT NOT NULL,
-- Condition
condition JSONB NOT NULL,
-- Example conditions:
-- { "operator": "<", "value": 2.50 }
-- { "operator": "change_pct", "value": 5, "direction": "down" }
-- { "operator": "steam", "threshold": 0.03 }
-- Notification preferences
channels TEXT[] DEFAULT ARRAY['push'],
message_template TEXT,
-- State
status alert_status DEFAULT 'active',
triggered_at TIMESTAMPTZ,
trigger_count INTEGER DEFAULT 0,
max_triggers INTEGER DEFAULT 1,
-- Validity
expires_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE alert_history (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
alert_rule_id UUID REFERENCES alert_rules(id),
user_id UUID NOT NULL,
triggered_at TIMESTAMPTZ DEFAULT NOW(),
trigger_data JSONB NOT NULL,
notification_sent BOOLEAN DEFAULT false,
notification_channels TEXT[]
);
CREATE INDEX idx_alert_rules_active ON alert_rules(user_id, status) WHERE status = 'active';
CREATE INDEX idx_alert_rules_target ON alert_rules(target_type, target_id) WHERE status = 'active';
2.4 Position Tracking Schema
-- Cached positions from backend (real-time sync)
CREATE TABLE user_positions (
id UUID PRIMARY KEY, -- Same ID as backend
user_id UUID NOT NULL REFERENCES user_context(user_id),
-- Position details
selection_id TEXT NOT NULL,
selection_name TEXT NOT NULL,
event_id TEXT NOT NULL,
event_name TEXT NOT NULL,
market_type TEXT NOT NULL,
-- Bet details
side TEXT NOT NULL, -- 'back' or 'lay'
stake DECIMAL(12,2) NOT NULL,
odds DECIMAL(10,4) NOT NULL,
placed_at TIMESTAMPTZ NOT NULL,
-- Current state
status TEXT NOT NULL, -- 'open', 'partial', 'settled', 'voided'
current_price DECIMAL(10,4),
cash_out_value DECIMAL(12,2),
unrealized_pnl DECIMAL(12,2),
-- Settlement
settled_at TIMESTAMPTZ,
result TEXT, -- 'won', 'lost', 'pushed'
realized_pnl DECIMAL(12,2),
-- Sync tracking
synced_from_backend_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_positions_user_open ON user_positions(user_id, status) WHERE status = 'open';
CREATE INDEX idx_positions_selection ON user_positions(selection_id) WHERE status = 'open';
2.5 Strategy Rules Schema
CREATE TYPE rule_action AS ENUM (
'block_bet', 'require_confirmation', 'adjust_stake',
'send_warning', 'log_only'
);
CREATE TABLE strategy_rules (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES user_context(user_id),
name TEXT NOT NULL,
description TEXT,
is_active BOOLEAN DEFAULT true,
priority INTEGER DEFAULT 100, -- Lower = higher priority
-- Rule condition (evaluated as boolean expression)
condition JSONB NOT NULL,
-- Examples:
-- { "type": "time_restriction", "after": "22:00", "before": "06:00" }
-- { "type": "stake_limit", "max_stake": 500 }
-- { "type": "loss_limit", "max_daily_loss": 1000 }
-- { "type": "sport_restriction", "blocked_sports": ["esports"] }
-- { "type": "odds_range", "min_odds": 1.5, "max_odds": 5.0 }
-- { "type": "confidence_requirement", "min_stars": 2 }
action rule_action NOT NULL,
action_params JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE strategy_rule_triggers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
rule_id UUID REFERENCES strategy_rules(id),
user_id UUID NOT NULL,
triggered_at TIMESTAMPTZ DEFAULT NOW(),
context JSONB NOT NULL, -- What triggered the rule
action_taken rule_action NOT NULL,
outcome TEXT -- 'blocked', 'warned', 'adjusted', 'confirmed'
);
2.6 Event Streaming (Redis)
# Redis Pub/Sub Channels
channels:
# Price updates (existing)
prices:{selection_id}:
payload: { selection_id, back, lay, timestamp }
# User-specific channels (new)
user:{user_id}:positions:
payload: { position_id, current_price, pnl, cash_out }
user:{user_id}:alerts:
payload: { alert_id, type, message, data }
user:{user_id}:notifications:
payload: { notification_id, channel, title, body }
# Global channels (new)
steam_moves:
payload: { selection_id, name, old_price, new_price, pct_change }
value_signals:
payload: { selection_id, name, edge, confidence, signal_type }
arbitrage:
payload: { selections, combined_roi, expiry }
3. API Contracts
3.1 User Context Service API
# Base: /api/user-context
GET /me:
description: Get current user's context and preferences
auth: required (JWT)
response:
user_id: uuid
display_name: string
preferences: object
stats:
total_bets: number
win_rate: number
total_pnl: number
favorite_sports: string[]
favorite_markets: string[]
PATCH /preferences:
description: Update user preferences
auth: required
body:
default_stake?: number
odds_format?: 'decimal' | 'american' | 'fractional'
timezone?: string
risk_level?: 'low' | 'medium' | 'high'
notification_channels?: string[]
response:
preferences: object
POST /sync:
description: Force sync user data from backend
auth: required
response:
synced: boolean
stats: object
3.2 Watchlist Service API
# Base: /api/watchlists
GET /:
description: Get all user's watchlists
auth: required
response:
watchlists: Watchlist[]
POST /:
description: Create new watchlist
auth: required
body:
name: string
description?: string
response:
watchlist: Watchlist
GET /{watchlist_id}:
description: Get watchlist with items
auth: required
response:
watchlist: Watchlist
items: WatchlistItem[]
POST /{watchlist_id}/items:
description: Add item to watchlist
auth: required
body:
item_type: 'selection' | 'event' | 'market' | 'team'
item_id: string
item_name: string
notes?: string
response:
item: WatchlistItem
DELETE /{watchlist_id}/items/{item_id}:
description: Remove item from watchlist
auth: required
POST /{watchlist_id}/share:
description: Generate share link for watchlist
auth: required
response:
share_code: string
share_url: string
GET /shared/{share_code}:
description: Get shared watchlist (public)
response:
watchlist: Watchlist
items: WatchlistItem[]
3.3 Alert Engine API
# Base: /api/alerts
GET /:
description: Get user's alert rules
auth: required
query:
status?: 'active' | 'triggered' | 'all'
response:
alerts: AlertRule[]
POST /:
description: Create new alert
auth: required
body:
alert_type: AlertType
target_type: string
target_id: string
target_name: string
condition: object
channels?: string[]
expires_at?: datetime
response:
alert: AlertRule
DELETE /{alert_id}:
description: Delete alert
auth: required
GET /history:
description: Get alert trigger history
auth: required
query:
limit?: number
response:
history: AlertHistory[]
# WebSocket for real-time alerts
WS /ws/alerts:
auth: required (token in query)
subscribe: automatic for user
messages:
- type: 'alert_triggered'
payload: { alert_id, type, message, data }
3.4 Position Tracker API
# Base: /api/positions
GET /:
description: Get user's positions
auth: required
query:
status?: 'open' | 'settled' | 'all'
sport?: string
limit?: number
response:
positions: Position[]
summary:
total_open: number
total_stake: number
unrealized_pnl: number
GET /{position_id}:
description: Get position details with cash out
auth: required
response:
position: Position
cash_out:
value: number
hedge_stake: number
break_even_price: number
price_history: PricePoint[]
GET /by-selection/{selection_id}:
description: Get positions for a selection
auth: required
response:
positions: Position[]
aggregate:
net_exposure: number
total_stake: number
POST /sync:
description: Force sync positions from backend
auth: required
response:
synced: number
positions: Position[]
# WebSocket for position updates
WS /ws/positions:
auth: required
messages:
- type: 'position_update'
payload: { position_id, current_price, pnl, cash_out }
- type: 'position_settled'
payload: { position_id, result, pnl }
3.5 Strategy Engine API
# Base: /api/strategy
GET /rules:
description: Get user's strategy rules
auth: required
response:
rules: StrategyRule[]
POST /rules:
description: Create strategy rule
auth: required
body:
name: string
description?: string
condition: RuleCondition
action: RuleAction
priority?: number
response:
rule: StrategyRule
PATCH /rules/{rule_id}:
description: Update strategy rule
auth: required
body:
is_active?: boolean
condition?: RuleCondition
action?: RuleAction
DELETE /rules/{rule_id}:
description: Delete strategy rule
auth: required
POST /evaluate:
description: Evaluate bet against rules
auth: required
body:
selection_id: string
stake: number
odds: number
sport?: string
market_type?: string
response:
allowed: boolean
triggered_rules: TriggeredRule[]
suggested_stake?: number
warnings: string[]
GET /rules/triggers:
description: Get rule trigger history
auth: required
query:
limit?: number
response:
triggers: RuleTrigger[]
3.6 Enhanced AI Chat API
# Base: /api/chat (enhanced)
POST /stream:
description: Stream chat response with user context
auth: required
body:
message: string
session_id?: string
context:
current_selection_id?: string
current_event_id?: string
include_positions?: boolean
include_watchlist?: boolean
response: SSE stream
- event: 'token'
data: { content: string }
- event: 'tool_call'
data: { tool: string, args: object }
- event: 'tool_result'
data: { tool: string, result: object }
- event: 'done'
data: { session_id: string }
GET /sessions:
description: Get user's chat sessions
auth: required
response:
sessions: ChatSession[]
GET /sessions/{session_id}:
description: Get session history
auth: required
response:
session: ChatSession
messages: ChatMessage[]
# New tools available with user context:
tools:
- get_my_positions: Get user's open positions
- get_my_watchlist: Get user's watchlist items
- get_my_stats: Get user's betting statistics
- check_my_rules: Check if bet passes strategy rules
- get_my_alerts: Get user's active alerts
- create_alert: Create a new price alert
- add_to_watchlist: Add item to user's watchlist
4. Feature Specifications
4.1 User Context Integration
Purpose: Enable all SuperSkin services to understand who the user is and personalize accordingly.
Architecture:
┌─────────────────────────────────────────────────────────────────┐
│ API Gateway │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ JWT Validation Middleware │ │
│ │ 1. Extract JWT from Authorization header │ │
│ │ 2. Validate signature with backend public key │ │
│ │ 3. Extract user_id, roles, permissions │ │
│ │ 4. Attach to request context │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ User Context Service │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Context Cache│ │ Preference │ │ Stats Sync Worker │ │
│ │ (Redis 5min) │ │ Manager │ │ (Every 5 min) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ smartbets-protocol│ │
│ │ /api/users/me │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Data Flow:
- User authenticates via smartbets-protocol → receives JWT
- Frontend includes JWT in all SuperSkin API calls
- API Gateway validates JWT, extracts user_id
- User Context Service checks Redis cache
- If miss: fetch from backend, cache for 5 minutes
- Services receive enriched request with user context
Implementation Notes:
- JWT secret shared between backend and SuperSkin (or use JWKS endpoint)
- User preferences stored in SuperSkin Supabase for fast access
- Betting stats synced from backend every 5 minutes via background job
- RLS policies ensure users only see their own data
4.2 Watchlist & Alerts System
Purpose: Let users track selections, get notified on price movements, and act on opportunities.
Architecture:
┌────────────────────────────────────────────────────────────────────────────┐
│ Watchlist Service │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────────────┐ │
│ │ Watchlist CRUD │ │ Item Enrichment│ │ Share Management │ │
│ │ (Supabase) │ │ (Price Feed) │ │ (Share codes) │ │
│ └────────────────┘ └────────────────┘ └────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
┌────────────────────────────────┐ ┌─────────────────────────────────────┐
│ Alert Engine │ │ Price Feed │
│ ┌──────────────────────────┐ │ │ ┌─────────────────────────────┐ │
│ │ Rule Evaluator │◀─┼──┼──│ Price Stream (Redis Pub/Sub)│ │
│ │ - Subscribe to prices │ │ │ └─────────────────────────────┘ │
│ │ - Check against rules │ │ │ │
│ │ - Trigger notifications │ │ └─────────────────────────────────────┘
│ └──────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────┐ │
│ │ Notification Dispatcher │ │
│ │ - Push notifications │ │
│ │ - Email (SendGrid) │ │
│ │ - SMS (Twilio) │ │
│ │ - In-app WebSocket │ │
│ └──────────────────────────┘ │
└────────────────────────────────┘
Alert Rule Evaluation Flow:
# Pseudocode for Alert Engine
async def on_price_update(selection_id: str, price: PriceUpdate):
# 1. Get all active alerts for this selection
alerts = await get_active_alerts_for_selection(selection_id)
for alert in alerts:
# 2. Evaluate condition
triggered = evaluate_condition(alert.condition, price)
if triggered:
# 3. Record trigger
await record_alert_trigger(alert.id, price)
# 4. Send notification
await send_notification(
user_id=alert.user_id,
channels=alert.channels,
message=format_alert_message(alert, price)
)
# 5. Update alert status
if alert.trigger_count >= alert.max_triggers:
await deactivate_alert(alert.id)
Supported Alert Types:
| Type | Condition Example | Use Case |
|---|---|---|
price_above | { "value": 2.50 } | Alert when odds rise above threshold |
price_below | { "value": 2.00 } | Alert when odds drop below threshold |
price_change_pct | { "value": 5, "direction": "down" } | Steam move detection |
steam_move | { "threshold": 0.03 } | Significant price movement |
value_signal | { "min_edge": 0.05 } | Value bet opportunity |
arbitrage | { "min_roi": 0.01 } | Arbitrage opportunity |
match_start | { "minutes_before": 30 } | Pre-match reminder |
position_pnl | { "target_pnl": 100 } | Cash out target reached |
4.3 Position Tracking System
Purpose: Real-time awareness of user's betting positions across all SuperSkin services.
Architecture:
┌─────────────────────────────────────────────────────────────────────────┐
│ smartbets-protocol (Backend) │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Bet Placement │─────▶│ Position Store │─────▶│ Settlement │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │ │
│ │ Webhook / Polling │
│ ▼ │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Position Tracker Service │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Position Sync │─────▶│ Position Cache │─────▶│ P&L Calculator │ │
│ │ Worker │ │ (Supabase + │ │ │ │
│ │ (Poll every 30s)│ │ Redis) │ └─────────────────┘ │
│ └─────────────────┘ └────────┬────────┘ │
│ │ │
│ ┌─────────────────┐ │ │
│ │ Price Enrichment│◀──────────────┘ │
│ │ (Subscribe to │ │
│ │ price updates) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Real-time P&L Updates │ │
│ │ - Calculate unrealized P&L on each price tick │ │
│ │ - Calculate cash out value │ │
│ │ - Push to user:{user_id}:positions channel │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Position Sync Strategy:
| Method | Frequency | Purpose |
|---|---|---|
| Polling | Every 30s | Catch new bets, settlements |
| Webhook | Real-time | Immediate position updates (if backend supports) |
| On-demand | User action | Force sync on page load |
P&L Calculation:
interface PositionPnL {
position_id: string;
stake: number;
odds: number;
side: 'back' | 'lay';
current_price: number;
// Calculated fields
unrealized_pnl: number;
cash_out_value: number;
break_even_price: number;
// Percentage
pnl_percentage: number;
}
function calculatePnL(position: Position, currentPrice: number): PositionPnL {
if (position.side === 'back') {
// Backed at odds, can lay now
const cashOut = position.stake * (position.odds / currentPrice);
const unrealized = cashOut - position.stake;
return {
...position,
current_price: currentPrice,
unrealized_pnl: unrealized,
cash_out_value: cashOut,
break_even_price: position.odds,
pnl_percentage: (unrealized / position.stake) * 100
};
} else {
// Laid at odds, can back now
const liability = position.stake * (position.odds - 1);
const cashOut = liability - (position.stake * (currentPrice - 1));
return {
...position,
current_price: currentPrice,
unrealized_pnl: cashOut,
cash_out_value: position.stake + cashOut,
break_even_price: position.odds,
pnl_percentage: (cashOut / liability) * 100
};
}
}
4.4 Strategy & Rules Engine
Purpose: Allow users to define betting rules and constraints that are enforced before bet placement.
Rule Types:
| Category | Rule Type | Example |
|---|---|---|
| Time | Time restriction | Block betting 10 PM - 6 AM |
| Stake | Stake limits | Max ₹500 per bet, Max ₹5000 daily |
| Loss | Loss limits | Stop after ₹1000 daily loss |
| Sport | Sport restriction | Only bet on Football, Cricket |
| Market | Market restriction | Only Match Odds, not corners |
| Odds | Odds range | Only bet on odds 1.5 - 5.0 |
| Confidence | Value threshold | Only bet on ⭐⭐⭐ signals |
| Frequency | Bet frequency | Max 10 bets per day |
Evaluation Flow:
┌─────────────────────────────────────────────────────────────────┐
│ Bet Placement Request │
│ { selection_id, stake, odds, sport, market_type } │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Strategy Engine │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ 1. Load user's active rules (ordered by priority) │ │
│ │ 2. For each rule: │ │
│ │ - Evaluate condition against bet context │ │
│ │ - If triggered, apply action │ │
│ │ 3. Aggregate results │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Evaluation Result │
│ { │
│ allowed: boolean, │
│ triggered_rules: [ │
│ { rule_id, name, action: 'block_bet', reason: '...' } │
│ ], │
│ suggested_stake: 250, // If stake adjusted │
│ warnings: ['You have 8/10 bets today'] │
│ } │
└─────────────────────────────────────────────────────────────────┘
Pre-built Strategy Templates:
const STRATEGY_TEMPLATES = {
conservative: {
name: 'Conservative',
rules: [
{ type: 'stake_limit', max_stake: 200 },
{ type: 'odds_range', min_odds: 1.4, max_odds: 3.0 },
{ type: 'loss_limit', max_daily_loss: 500 },
{ type: 'confidence_requirement', min_stars: 2 },
]
},
valueHunter: {
name: 'Value Hunter',
rules: [
{ type: 'confidence_requirement', min_stars: 3 },
{ type: 'odds_range', min_odds: 2.0, max_odds: 10.0 },
{ type: 'stake_calculation', method: 'kelly', fraction: 0.25 },
]
},
nightOwlBlock: {
name: 'Night Owl Block',
rules: [
{ type: 'time_restriction', after: '23:00', before: '07:00' },
]
}
};
4.5 Enhanced AI Chat with User Context
Purpose: Make the AI assistant aware of the user's betting history, positions, preferences, and watchlist.
System Prompt Enhancement:
def build_system_prompt(user_context: UserContext) -> str:
return f"""You are Forsyt AI, a betting intelligence assistant.
## User Profile
- Name: {user_context.display_name}
- Total Bets: {user_context.stats.total_bets}
- Win Rate: {user_context.stats.win_rate:.1%}
- Total P&L: ₹{user_context.stats.total_pnl:,.2f}
- Favorite Sports: {', '.join(user_context.favorite_sports)}
## User's Current State
- Open Positions: {len(user_context.positions)} (₹{sum(p.stake for p in user_context.positions):,.0f} at stake)
- Watchlist Items: {len(user_context.watchlist)} selections being tracked
- Active Alerts: {len(user_context.alerts)} price alerts set
## User Preferences
- Default Stake: ₹{user_context.preferences.default_stake}
- Risk Level: {user_context.preferences.risk_level}
- Odds Format: {user_context.preferences.odds_format}
When the user asks about "my bets", "my positions", "my watchlist", or "my performance",
use the tools to fetch their actual data and provide personalized insights.
"""
New AI Tools for User Context:
USER_CONTEXT_TOOLS = [
{
"type": "function",
"function": {
"name": "get_my_positions",
"description": "Get the user's open betting positions with current P&L",
"parameters": {
"type": "object",
"properties": {
"status": {"type": "string", "enum": ["open", "settled", "all"]},
"sport": {"type": "string", "description": "Filter by sport"}
}
}
}
},
{
"type": "function",
"function": {
"name": "get_my_watchlist",
"description": "Get items from the user's watchlist with current prices",
"parameters": {
"type": "object",
"properties": {
"watchlist_name": {"type": "string"}
}
}
}
},
{
"type": "function",
"function": {
"name": "get_my_performance",
"description": "Get user's betting performance statistics",
"parameters": {
"type": "object",
"properties": {
"period": {"type": "string", "enum": ["today", "week", "month", "all"]},
"sport": {"type": "string"},
"market_type": {"type": "string"}
}
}
}
},
{
"type": "function",
"function": {
"name": "create_alert",
"description": "Create a price alert for the user",
"parameters": {
"type": "object",
"properties": {
"selection_id": {"type": "string"},
"selection_name": {"type": "string"},
"alert_type": {"type": "string", "enum": ["price_above", "price_below", "steam_move"]},
"target_price": {"type": "number"}
},
"required": ["selection_id", "selection_name", "alert_type"]
}
}
},
{
"type": "function",
"function": {
"name": "add_to_watchlist",
"description": "Add a selection to the user's watchlist",
"parameters": {
"type": "object",
"properties": {
"selection_id": {"type": "string"},
"selection_name": {"type": "string"},
"notes": {"type": "string"}
},
"required": ["selection_id", "selection_name"]
}
}
},
{
"type": "function",
"function": {
"name": "check_strategy_rules",
"description": "Check if a potential bet passes the user's strategy rules",
"parameters": {
"type": "object",
"properties": {
"selection_id": {"type": "string"},
"stake": {"type": "number"},
"odds": {"type": "number"},
"sport": {"type": "string"}
},
"required": ["stake", "odds"]
}
}
}
]
5. Infrastructure
5.1 Service Deployment Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Ingress Controller │ │
│ │ (NGINX + Rate Limiting) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ API Gateway │ │
│ │ (Kong / Traefik / Custom) │ │
│ │ - JWT validation │ │
│ │ - Rate limiting per user │ │
│ │ - Request routing │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │ │ │ │ │ │
│ ┌──────┴──┐ ┌────┴────┐ ┌──┴───┐ ┌───┴───┐ ┌───┴───┐ ┌───┴───┐ │
│ │Price │ │Cash Out │ │AI │ │AI Chat│ │Trading│ │Shared │ │
│ │Feed x2 │ │Calc x2 │ │Value │ │x3 │ │Charts │ │Svc x2 │ │
│ │(Node) │ │(Node) │ │x2 Py │ │(Py) │ │(Node) │ │(Node) │ │
│ └────────┘ └─────────┘ └──────┘ └───────┘ └───────┘ └───────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Background Workers │ │
│ │ - Position Sync Worker (Python) │ │
│ │ - Alert Evaluation Worker (Python) │ │
│ │ - Stats Sync Worker (Python) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ Redis Cluster │ │ Supabase │ │ smartbets-protocol│
│ - Session cache │ │ - PostgreSQL │ │ - User data │
│ - Price pub/sub │ │ - Auth │ │ - Positions │
│ - Alert state │ │ - Realtime │ │ - History │
└────────────────────┘ └────────────────────┘ └────────────────────┘
5.2 Data Flow Patterns
Pattern 1: Authenticated Request Flow
User → API Gateway → JWT Validate → User Context (Redis) → Service → Response
Pattern 2: Real-time Price Updates
Price Feed → Redis Pub/Sub → Alert Engine (evaluate) → Notification Hub → Push/WebSocket
→ Position Tracker (P&L) → User WebSocket
→ Trading Charts (OHLC) → Chart Update
Pattern 3: Position Sync
Backend Webhook/Poll → Position Sync Worker → Supabase → Redis Cache → User WebSocket
5.3 Scaling Considerations
| Service | Scaling Strategy | Bottleneck |
|---|---|---|
| Price Feed | Horizontal, stateless | Redis pub/sub throughput |
| AI Chat | Horizontal, rate limited | Grok API rate limits |
| Alert Engine | Horizontal with partitioning | Active alert count |
| Position Tracker | Vertical (memory) | Position count per user |
5.4 Monitoring & Observability
metrics:
- service_response_time_ms
- service_error_rate
- active_websocket_connections
- redis_pubsub_lag_ms
- alert_evaluation_time_ms
- position_sync_lag_seconds
- grok_api_tokens_used
- user_session_count
alerts:
- name: HighErrorRate
condition: error_rate > 1%
severity: critical
- name: SlowAlertEvaluation
condition: alert_evaluation_time_ms > 500
severity: warning
- name: PositionSyncLag
condition: position_sync_lag_seconds > 60
severity: warning
- name: GrokRateLimitApproaching
condition: grok_requests_per_minute > 50
severity: warning
dashboards:
- SuperSkin Overview
- User Experience Metrics
- Alert Engine Performance
- AI Chat Analytics
- Position Tracking Health
6. Implementation Phases
Phase 1: User Context Foundation (Week 1-2)
Goal: Enable user identity across all SuperSkin services.
Deliverables:
- JWT validation middleware for all services
- User Context Service with caching
- User preferences CRUD API
- Background job for stats sync from backend
- RLS policies on all SuperSkin tables
Dependencies:
- smartbets-protocol JWT endpoint / shared secret
- Supabase project setup
Definition of Done:
- All service endpoints require authentication
- User context available in request handlers
- Preferences persisted and retrieved correctly
- Stats synced within 5 minutes of backend update
Phase 2: Watchlist & Basic Alerts (Week 3-4)
Goal: Let users track selections and get notified on price changes.
Deliverables:
- Watchlist Service (CRUD, sharing)
- Alert Engine with price-based rules
- WebSocket endpoint for real-time alerts
- Integration with existing notification service
- AI Chat tools:
add_to_watchlist,create_alert
Dependencies:
- Phase 1 (User Context)
- Notification service integration
Definition of Done:
- Users can create/manage watchlists
- Price alerts trigger notifications within 5 seconds
- WebSocket delivers alerts to connected clients
- AI can add items to watchlist via chat
Phase 3: Position Tracking (Week 5-6)
Goal: Real-time awareness of user positions with live P&L.
Deliverables:
- Position Sync Worker (polling backend)
- Position cache with Redis
- Real-time P&L calculation on price updates
- WebSocket endpoint for position updates
- AI Chat tools:
get_my_positions - Enhanced Cash Out with user positions
Dependencies:
- Phase 1 (User Context)
- Backend API for position retrieval
Definition of Done:
- Positions sync within 30 seconds of placement
- P&L updates on every price tick
- Cash out auto-calculated for open positions
- AI can discuss user's current positions
Phase 4: Strategy Engine (Week 7-8)
Goal: User-defined betting rules and constraints.
Deliverables:
- Strategy Rule CRUD API
- Rule evaluation engine
- Pre-built strategy templates
- Integration with bet placement flow
- AI Chat tools:
check_strategy_rules
Dependencies:
- Phase 1 (User Context)
- Phase 3 (Position Tracking for loss limits)
Definition of Done:
- Users can create custom rules
- Rules evaluated before bet placement
- Blocked bets show clear reason
- AI can evaluate hypothetical bets against rules
Phase 5: Advanced Features (Week 9-12)
Goal: Multi-leg bets, correlations, and advanced analytics.
Deliverables:
- Parlay builder with combined odds
- Multi-leg cash out calculation
- Market correlation analysis
- Portfolio overlay on charts
- Performance comparison to projections
- Partial cash out execution
Dependencies:
- All previous phases
Definition of Done:
- Users can build parlays
- Correlation alerts functional
- Portfolio P&L visible on charts
- AI can analyze multi-leg opportunities
7. Security Considerations
7.1 Authentication & Authorization
authentication:
method: JWT (from smartbets-protocol)
validation:
- Signature verification (RS256)
- Expiration check
- Issuer validation
authorization:
model: RBAC + Row Level Security
roles:
- user: Standard user access
- premium: Advanced features
- admin: Full access
rls_policies:
watchlists: user_id = auth.uid()
alert_rules: user_id = auth.uid()
user_positions: user_id = auth.uid()
strategy_rules: user_id = auth.uid()
7.2 Data Protection
sensitive_data:
encrypted_at_rest:
- User preferences
- Position history
- Strategy rules
not_logged:
- JWT tokens
- User stakes
- P&L values
anonymized_in_analytics:
- user_id → hash(user_id + salt)
7.3 Rate Limiting
rate_limits:
api_gateway:
- path: /api/chat/*
limit: 20 requests/minute/user
- path: /api/alerts
limit: 50 requests/minute/user
- path: /api/positions
limit: 100 requests/minute/user
websocket:
- connections_per_user: 5
- messages_per_second: 10
8. API Gateway Configuration
8.1 Route Definitions
routes:
# Existing services
- path: /api/prices/*
service: price-feed-aggregator
auth: optional
- path: /api/cashout/*
service: cash-out-calculator
auth: required
- path: /api/value/*
service: ai-value-detection
auth: optional
- path: /api/chat/*
service: ai-chat-assistant
auth: required
rate_limit: 20/min
- path: /api/charts/*
service: trading-charts
auth: optional
# New shared services
- path: /api/user-context/*
service: shared-services
auth: required
- path: /api/watchlists/*
service: shared-services
auth: required
- path: /api/alerts/*
service: shared-services
auth: required
- path: /api/positions/*
service: shared-services
auth: required
- path: /api/strategy/*
service: shared-services
auth: required
# WebSocket endpoints
- path: /ws/prices
service: price-feed-aggregator
type: websocket
auth: optional
- path: /ws/alerts
service: shared-services
type: websocket
auth: required
- path: /ws/positions
service: shared-services
type: websocket
auth: required
9. Appendix
9.1 Environment Variables
# Shared across all services
JWT_SECRET=xxx
JWT_ISSUER=smartbets-protocol
REDIS_URL=redis://redis:6379
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_SERVICE_KEY=xxx
# Backend integration
BACKEND_URL=https://api.smartbets.com
BACKEND_API_KEY=xxx
# Service-specific
GROK_API_KEY=xxx
GROK_MODEL=grok-4-fast
PRICE_FEED_URL=http://price-feed:3000
VALUE_DETECTION_URL=http://ai-value:8000
9.2 Database Migration Order
-- Run in order:
1. migrations/001_user_context.sql
2. migrations/002_watchlists.sql
3. migrations/003_alert_rules.sql
4. migrations/004_user_positions.sql
5. migrations/005_strategy_rules.sql
6. migrations/006_rls_policies.sql
9.3 Service Health Checks
health_checks:
price-feed-aggregator:
endpoint: /health
interval: 10s
timeout: 5s
shared-services:
endpoint: /health
checks:
- redis_connected
- supabase_connected
- backend_reachable
Document History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2026-01-12 | AI Architect | Initial architecture document |