Skip to main content

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

  1. User Context Everywhere - Every service call includes user identity
  2. Event-Driven - Services communicate via events for real-time updates
  3. Graceful Degradation - Features work standalone if dependencies fail
  4. Single Source of Truth - Backend platform owns user data, SuperSkin caches
  5. Security by Design - JWT auth, RLS policies, encrypted PII

Document Structure

This architecture is organized into the following sections:

  1. System Components - All services and their responsibilities
  2. Data Architecture - Schemas, storage, and data flows
  3. API Contracts - Service interfaces and protocols
  4. Feature Specifications - Detailed designs per feature
  5. Infrastructure - Deployment, scaling, monitoring
  6. Implementation Phases - Build order and dependencies

1. System Components

1.1 Existing Services (To Be Enhanced)

ServiceCurrent RoleEnhancement Needed
Price Feed AggregatorAggregate multi-book pricesAdd user preferences, favorites
Cash Out CalculatorCalculate cash out valuesConnect to user positions
AI Value DetectionDetect value opportunitiesTrack user performance
AI Chat AssistantConversational AIFull user context, history
Trading ChartsOHLC chart dataWatchlists, portfolio overlay

1.2 New Shared Services

ServiceResponsibilityKey Features
User Context ServiceUser identity & preferencesJWT validation, preference cache
Watchlist ServiceWatchlist & favorite trackingCRUD, sharing, notifications
Alert EnginePrice & event monitoringRule evaluation, triggers
Position TrackerLive position managementSync from backend, P&L
Strategy EngineRule-based constraintsStaking rules, limits
Notification HubMulti-channel deliveryPush, email, SMS routing

1.3 External Dependencies

SystemIntegration TypePurpose
smartbets-protocolREST APIUser data, betting history, positions
SupabasePostgreSQL + RealtimePersistent storage, real-time sync
RedisCache + Pub/SubSession cache, event streaming
Grok APILLM ProviderAI 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:

  1. User authenticates via smartbets-protocol → receives JWT
  2. Frontend includes JWT in all SuperSkin API calls
  3. API Gateway validates JWT, extracts user_id
  4. User Context Service checks Redis cache
  5. If miss: fetch from backend, cache for 5 minutes
  6. 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:

TypeCondition ExampleUse 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:

MethodFrequencyPurpose
PollingEvery 30sCatch new bets, settlements
WebhookReal-timeImmediate position updates (if backend supports)
On-demandUser actionForce 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:

CategoryRule TypeExample
TimeTime restrictionBlock betting 10 PM - 6 AM
StakeStake limitsMax ₹500 per bet, Max ₹5000 daily
LossLoss limitsStop after ₹1000 daily loss
SportSport restrictionOnly bet on Football, Cricket
MarketMarket restrictionOnly Match Odds, not corners
OddsOdds rangeOnly bet on odds 1.5 - 5.0
ConfidenceValue thresholdOnly bet on ⭐⭐⭐ signals
FrequencyBet frequencyMax 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

ServiceScaling StrategyBottleneck
Price FeedHorizontal, statelessRedis pub/sub throughput
AI ChatHorizontal, rate limitedGrok API rate limits
Alert EngineHorizontal with partitioningActive alert count
Position TrackerVertical (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:

  1. JWT validation middleware for all services
  2. User Context Service with caching
  3. User preferences CRUD API
  4. Background job for stats sync from backend
  5. 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:

  1. Watchlist Service (CRUD, sharing)
  2. Alert Engine with price-based rules
  3. WebSocket endpoint for real-time alerts
  4. Integration with existing notification service
  5. 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:

  1. Position Sync Worker (polling backend)
  2. Position cache with Redis
  3. Real-time P&L calculation on price updates
  4. WebSocket endpoint for position updates
  5. AI Chat tools: get_my_positions
  6. 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:

  1. Strategy Rule CRUD API
  2. Rule evaluation engine
  3. Pre-built strategy templates
  4. Integration with bet placement flow
  5. 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:

  1. Parlay builder with combined odds
  2. Multi-leg cash out calculation
  3. Market correlation analysis
  4. Portfolio overlay on charts
  5. Performance comparison to projections
  6. 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

VersionDateAuthorChanges
1.02026-01-12AI ArchitectInitial architecture document