v1.0 · April 2026

Jugalbandi Architecture

Wealth management has a context problem, not a technology problem. The RM has portfolio data. The client has a life. Neither side sees the other. This is the architecture that connects them.

The client dashboard is a signal-collection instrument disguised as a portfolio viewer. The RM command center is a context engine disguised as a task list. They share one Intelligence Graph.
3Signal Types
47AI Functions
4Custodians
7Packages
2Apps
13DB Tables
01

The Intelligence Graph

A living, per-client model that combines three signal types no other system connects

Every wealth platform has hard data. Positions, NAVs, transactions. That's table stakes. The Intelligence Graph is what happens when you add the two signal types no custodian provides: what the client does on their dashboard, and what the RM knows about the client's life.

Hard Data
Custodians, brokers, PMS, Account Aggregator
  • Positions across CAMS, KFintech, NSDL, CDSL
  • NAV, units, avg buy price, XIRR per holding
  • Transaction history, SIP schedules, dividends
  • FD details, NPS balance, bank statements via AA
Available everywhere. Not the novel part.
Behavioral Signals
Client dashboard telemetry — silent, continuous
  • Checked pharma holdings 6x between 2–5 AM
  • Didn't open app for 11 days after a 4% drawdown
  • Searched 'SGB maturity' three times in one week
  • Exported portfolio PDF the day after a market fall
This is the novel signal. No custodian has it.
RM-Contributed Context
RM notes, meeting prep, post-call observations
  • "Daughter's wedding March 2026 — needs ₹2Cr liquid"
  • "Doesn't trust structured products since 2008"
  • "Responds well to data-backed reassurance, not optimism"
  • "Patriarch makes all decisions. Son is a formality."
Human judgment, encoded. Persists across RM turnover.
These three signals combine into one per-client model
Hard Data
+
Behavioral Signals
+
RM Context
=
Client Intelligence Graph
Without the graph
“Call Mr. Sharma. His portfolio dropped 3.2%.”
With the graph
“Mr. Sharma has checked his healthcare holdings 4 times since Monday. He hasn't called you. Last time this pattern occurred (Sept 2024), he panic-sold Biocon and regretted it in two weeks. His daughter's medical school fees are partially funded from those holdings. He responds well to data-backed reassurance, not general optimism.”

The second briefing reads like a senior colleague's note. It is produced entirely by the system, from signals the RM never had to think about collecting. That is the only design goal of the Intelligence Graph.

02

Data Pipeline

How custodian data flows into the graph — four integrations, one schema, zero floats

Custodian Integrations

CustodianIntegrationAuthData RetrievedSync
CAMS (MF)API + CAS ParserOAuth 2.0 + PAN verificationHoldings, transactions, SIP details, dividendsDaily 6 AM IST
KFintech (MF)API + CAS ParserOAuth 2.0 + PAN verificationHoldings, transactions, SIP detailsDaily 6 AM IST
NSDL (Demat)CDAS APIDigital signature + 2FAEquity holdings, corporate actions, IPO allotmentsReal-time webhook
CDSL (Demat)easi/easiest API2FA + OTPEquity holdings, transactionsReal-time webhook
Account AggregatorAA API (ReBIT spec)Consent artifact (FI-based)Bank statements, FDs, insurance, NPSOn consent, then scheduled

Ingestion Pipeline

Raw Sources
CAMS, KFintech, NSDL, CDSL, AA framework, manual uploads
Normalizer
Map custodian-specific formats to unified Intelligence Graph schema. All amounts to paisa (BIGINT).
Deduplicator
Same ISIN held at CAMS and KFintech? Merge. Cross-reference by PAN + ISIN + date.
Validator
Paisa check: all BIGINT, no floats. NAV cross-check vs AMFI published values. Units > 0. Dates sane.
Enricher
Add ISIN/AMFI code, sector, benchmark, geography, asset class. Tag corporate actions. Link to client goals.
Intelligence Graph
Write to holdings, transactions, custodian_accounts. Trigger materialized view refresh for AUM rollups.
DLQFailed records routed to Dead Letter Queue for manual review. Alerts RM if client-impacting. Auto-retry with exponential backoff (max 3 attempts). Client sees last-known-good values until resolved.

Market Data Feeds

SourceDataFrequencyProtocol
NSE (via Data Vendor)Real-time equity prices, indicesEvery 1s during market hoursWebSocket
AMFI NAV APIMutual fund NAVsDaily EOD (9 PM IST)REST (amfiindia.com)
RBI Reference RatesCurrency rates, SGB pricesDailyREST
BSEBond prices, debt instrumentsEvery 15sREST API
CRISIL / ICRACredit ratings, bond yieldsOn changeWebhook
03

The AI Layer

Not a chatbot. Not RAG. Full context window reasoning on the Intelligence Graph.

The AI layer reads the entire Intelligence Graph for a client — all three signal types, full history, RM notes, goals — and produces context. Not instructions. Not chat responses. Context that makes the RM's natural judgment produce the right action.

Models & Roles

ModelRole in the thesisInputLatency
Claude Opus 3Deep synthesis — morning briefings, meeting prep, Council Mode (5-perspective analysis)Full client Intelligence Graph<8s
Claude Sonnet 3.5Context synthesis — pattern matching, action generation, weekly digestsSignal array + RM notes + holdings<3s
Claude Haiku 3.5Real-time classification — every client action classified as it happensIndividual signal event<500ms
text-embedding-3-smallRM note similarity search — “when did we last discuss this?”Note text<200ms

Signal Detection 8 functions

FunctionWhat it detectsModelTrigger
classifySignal()Type, severity, pattern match from raw telemetryHaikuEvery client action
detectAnxietyCluster()Repeated holding checks in short windows — signals stress before the client callsSonnetHourly batch
detectLoginAnomaly()2 AM logins, unusual devices, location changesRule-basedEvery login
classifySearchIntent()What the client is worried about from their search queryHaikuEvery search
detectGoalDrift()Transactions that move away from the investment mandateRule-based + HaikuEvery transaction
aggregateSignals()Cluster all signals per client into a priority scoreSonnet6 AM daily
detectExportPattern()Unusual PDF exports — often precedes RM switch discussionsHaikuEvery export
scoreEngagement()30-day trend — rising engagement vs risk of churnRule-basedDaily

Context Synthesis 10 functions

FunctionWhat it producesModelTrigger
generateMorningBrief()Prioritized briefing for all clients — who needs a call today and whyOpus6 AM daily
generateClientContext()Full Intelligence Graph synthesis for one client on demandSonnetOn demand
generateMeetingPrep()Agenda, talking points, personality profile, risk flags — 2h before meetingOpusCalendar trigger
synthesizeCouncilMode()5 parallel perspectives (Portfolio, Behavioral, Tax, Risk, Relationship) + synthesisOpusOn demand
matchHistoricalPattern()“Last time this happened (Sept 2024)” — the sentence that changes RM behaviorSonnet + VectorWith every synthesis
generateActionItems()Specific actions with owner, priority, deadline — never generic adviceSonnetWith every synthesis
generateThinkingChain()Full transparency: which signals went in, what patterns were matched, whySonnetWith every synthesis
scoreConfidence()Confidence % on every synthesis output — RM sees the uncertaintyRule-basedWith every synthesis
generateWeeklyDigest()7-day summary for RM — what changed, what to watchSonnetWeekly
summarizeForClient()Strip RM-only context, produce client-safe version of the same analysisHaikuOn demand

Financial Calculations 12 functions

FunctionWhat it calculatesImplementation
calculateXIRR()Annualized return on irregular cashflows, SIP-awareNewton-Raphson (in-house)
calculatePortfolioXIRR()Weighted XIRR across all holdings, multi-custodian unifiedIn-house
calculateLTCG()Long-term capital gains with Budget 2025-26 rules and grandfatheringIn-house
calculateSTCG()Short-term capital gains at 20% rateIn-house
calculateDebtTax()Debt fund tax at slab rate, no indexation post-2023In-house
simulateTaxHarvest()Sell + rebuy vs hold: net tax savings with all costs factoredIn-house + Haiku
projectGoal()Goal projection with probability distribution — 10,000 Monte Carlo runsMonte Carlo (in-house)
calculateAttribution()Why did the portfolio return X? Brinson-Fachler decomposition.In-house
reconcileMultiCustodian()Same ISIN across custodians — unify, flag conflicts, surface errorsRule-based + Haiku
calculateDayChange()Today's P&L across all holdings in paisaIn-house
formatIndianCurrency()BIGINT paisa → “₹12,84,700” — Indian locale, lakh/crore groupingPure function
calculateRebalance()Trades to reach target allocation with tax impact and tracking errorConstraint optimization

Supporting Functions 17 functions

Behavioral Tracking (4)
trackPageView()trackHoldingCheck()trackSearchQuery()trackExportRequest()
Communication (6)
encryptMessage()decryptMessage()formatMessageForDisplay()detectFinancialFigures()generateDocumentSummary()trackMessageSentiment()
Security & Compliance (7)
enforceRLS()hashPAN()auditLog()validateSession()checkFATCA()validateInvestmentMandate()detectAMLPattern()
04

The Dual Interface

Same Intelligence Graph. Two instruments. Each responds to the other's cues.

These are not two products. The client's behavior on their dashboard is intent data the RM never gets. The RM's context about the client is what makes the dashboard feel personally built. One graph. Two interfaces. A flywheel.

Client Dashboard
apps/client · Next.js 15 · App Router
  • Unified portfolio view across all custodians
  • Attribution: why did my portfolio return X%?
  • Tax impact simulation before rebalancing
  • Document vault with full audit trail
  • Encrypted messaging (WhatsApp-feel, not support ticket)
Every page view, holding check, search query, and export is captured as a behavioral signal. The client sees a portfolio viewer. The system sees intent data.
Client Intelligence
Graph
RM Command Center
apps/rm · Next.js 15 · App Router
  • Morning briefing: synthesized overnight changes across all clients
  • Priority queue: ranked by signal urgency, not alphabetical
  • Client deep-dive: full Intelligence Graph for meeting prep
  • Post-meeting notes: feed directly back into the graph
  • Council Mode: 5-perspective analysis for complex situations
The RM does not see raw clickstream. They see synthesized context. The graph produces the insight. The RM provides the judgment.

From Client Action to RM Briefing

1
Client checks healthcare holdings at 2 AM
trackPageView() and trackHoldingCheck() fire silently. Both write to behavioral_signals table with timestamp, context, time-of-day flag.
2
Signal classified in real-time
classifySignal() via Haiku: type 'holding_check', severity 'elevated'. Time-of-day (2 AM) increases severity score automatically.
3
Anxiety pattern detected
detectAnxietyCluster() on 48h window: 6 checks in 3 hours on healthcare. matchHistoricalPattern() returns Sept 2024 Biocon episode. Confidence: 87%.
4
Context snapshot generated
generateClientContext() synthesizes: signals + historical match + RM notes about daughter's medical school fees + client's communication style.
5
RM morning briefing
8 AM: RM sees 'Mr. Sharma checked healthcare holdings 6x (2-5 AM). Pattern matches Sept 2024 Biocon panic sell. Medical school fees funded from these holdings. Responds well to data-backed reassurance.'

Morning Briefing Generation

1
Cron 5:30 AM
Fetch overnight signals for all clients. Threshold check: clients with signals > 3 proceed to processing pipeline.
2
Signal processing per client
aggregateSignals() clusters by type. detectAnxietyCluster() checks for stress patterns. scoreEngagement() computes 30-day trend.
3
Priority ranking
Composite priority_score: anxiety 40%, portfolio change 30%, engagement shift 20%, calendar proximity 10%. All clients ranked.
4
Briefing generation
Top 10 clients sent to generateMorningBrief() via Claude Opus. Full Intelligence Graph context. Output: structured briefing with talking points, risk flags, suggested actions.
5
Storage + delivery
Stored in context_snapshots (type: morning_briefing). Push notification to RM app. RM opens at 8 AM and sees streaming text render.

Monorepo Structure

APPLICATIONS
apps/client
Client Dashboard
apps/rm
RM Command Center
↓   ↓
DOMAIN PACKAGES
packages/intelligence
Signal Types, Graph Query, Pattern Processing
packages/ai
LLM Orchestration, Prompts, Streaming
packages/finance
XIRR, Tax, Attribution, Monte Carlo
DATA & DESIGN
packages/supabase
Schema, RLS Policies, Typed Client, Edge Functions
packages/ui
Design System, Tokens, Shared Components
packages/shared
Types, Utils, Constants, Formatters
05

Security Architecture

UHNI clients demand this. Six layers from network edge to AI safety.

Layer 1Network
  • Vercel Edge Network — global DDoS protection, 300+ PoPs
  • HTTPS everywhere with HSTS preload header
  • Rate limiting: 100 req/min per client, 500 req/min per RM
  • Geo-restricted to India (configurable per deployment)
Layer 2Authentication
  • Client: Magic link (email) — no passwords for UHNI. Google OAuth secondary.
  • RM: SAML SSO via firm identity provider + OTP fallback
  • Session: Supabase Auth (JWT, 1hr expiry, automatic refresh)
  • Invite-only: no self-registration — clients onboarded by their RM
Layer 3Authorization
  • Row Level Security (RLS) on ALL 13 tables — no exceptions
  • Client role: sees own data only (client_id = auth.uid())
  • RM role: sees assigned clients only (rm_id = auth.uid())
  • RM Admin role: sees team clients (team matching)
  • No cross-tenant data leakage possible at database level
Layer 4Data Protection
  • PAN: SHA-256 hashed with per-client salt — never stored raw
  • Messages: AES-256-GCM end-to-end encryption — server cannot read
  • Documents: encrypted at rest (AES-256) via Supabase Storage
  • Account numbers: one-way hashed — displayed as masked (****1234)
  • All money: BIGINT paisa — no floating point errors, ever
Layer 5Audit & Compliance
  • Append-only audit log: every action recorded, no UPDATE or DELETE
  • IP address + user agent + timestamp on every log entry
  • RBI data residency: all data in India-region Supabase instance
  • DPDP Act 2023: consent management, data minimization, right to erasure
  • SEBI advisory: investment mandate validation on every transaction
Layer 6AI Safety
  • No PII in LLM prompts: client names anonymized before sending to Claude
  • No financial advice in AI output: context and analysis only, never 'buy' or 'sell'
  • Confidence scoring on all AI outputs: RM sees the % and contributing factors
  • Human-in-the-loop: RM reviews and approves all AI-generated action items
  • Thinking chain: full transparency on how every briefing was generated
06

Database Schema

13 tables. Every one with RLS. All money in paisa. The novel tables are highlighted.

The three Intelligence Graph tables — behavioral_signals, rm_context_notes, and context_snapshots — are what make this system different. Every other wealth platform has the first six tables. Only Jugalbandi has the last three.

Intelligence Graph Tables the novel ones

BEHAVIORAL_SIGNALS
signal_id — PK, UUID, gen_random_uuid()
client_id — FK → clients
signal_type — ENUM (page_view, holding_check, document_access, message_sent, login_pattern, search_query, export_request, feature_interaction)
signal_data — JSONB (event payload)
source — ENUM (client_dashboard, rm_input, system_detected)
created_at — TIMESTAMPTZ DEFAULT now()
expires_at — TIMESTAMPTZ (TTL for raw telemetry)
RLS: Client: NONE — telemetry is not exposed to client. RM: assigned client signals. System: write-only.
RM_CONTEXT_NOTES
note_id — PK, UUID
rm_id — FK → relationship_managers
client_id — FK → clients
note_type — ENUM (general, meeting, call, observation, strategy)
content — TEXT (encrypted at rest)
tags — TEXT[]
linked_holdings — UUID[]
linked_goals — UUID[]
is_meeting_note — BOOLEAN DEFAULT false
meeting_date — DATE
sentiment_score — NUMERIC(3,2) (AI-generated)
created_at — TIMESTAMPTZ
RLS: Client: filtered view (no RM-only tags). RM: own notes for assigned clients only.
CONTEXT_SNAPSHOTS
snapshot_id — PK, UUID
client_id — FK → clients
rm_id — FK → relationship_managers
snapshot_type — ENUM (morning_briefing, meeting_prep, alert, quarterly_review)
signals_considered — JSONB (audit: exactly what went into this)
context_output — TEXT (the synthesized briefing — plain language)
confidence — NUMERIC(5,2)
priority_score — INT (0–100)
created_at — TIMESTAMPTZ
read_at — TIMESTAMPTZ
RLS: Client: NONE. RM: own snapshots for assigned clients only.

Core Tables every platform has these

CLIENTS
client_id — PK, UUID
rm_id — FK → relationship_managers
family_office_id — FK? → family_offices
full_name — TEXT NOT NULL
pan_hash — TEXT (SHA-256 with salt, never raw)
risk_profile — ENUM (conservative, moderate, aggressive, custom)
investment_mandate — JSONB
kyc_status — ENUM (pending, verified, expired)
aml_status — ENUM (clear, flagged, under_review)
fatca_status — ENUM (compliant, non_compliant, pending)
total_aum_paisa — BIGINT (materialized view)
relationship_start_date — DATE
created_at — TIMESTAMPTZ
RLS: Client: own row only. RM: assigned clients. RM Admin: team clients.
HOLDINGS
holding_id — PK, UUID
client_id — FK → clients
account_id — FK → custodian_accounts
asset_type — ENUM (mutual_fund, stock, bond, fd, ppf, nps, pms, aif, real_estate, gold, unlisted, other)
asset_code — TEXT (AMFI/ISIN/custom)
asset_name — TEXT
units — NUMERIC(20,6)
avg_buy_price_paisa — BIGINT
current_nav_paisa — BIGINT
invested_paisa — BIGINT
current_value_paisa — BIGINT
xirr — NUMERIC(8,4)
geography — TEXT
currency — TEXT DEFAULT 'INR'
updated_at — TIMESTAMPTZ
RLS: Client: own holdings. RM: assigned client holdings.
TRANSACTIONS
transaction_id — PK, UUID
client_id — FK → clients
account_id — FK → custodian_accounts
holding_id — FK → holdings
amount_paisa — BIGINT NOT NULL
direction — ENUM (buy, sell, dividend, switch_in, switch_out, sip)
transaction_date — DATE NOT NULL
settlement_date — DATE
corporate_action_ref — TEXT (nullable)
created_at — TIMESTAMPTZ
RLS: Client: own transactions. RM: assigned client transactions.
CLIENT_GOALS
goal_id — PK, UUID
client_id — FK → clients
title — TEXT NOT NULL
target_paisa — BIGINT
current_paisa — BIGINT (materialized)
target_date — DATE
linked_holdings — UUID[]
strategy_notes — TEXT
priority — INT (1–5)
status — ENUM (active, achieved, abandoned, paused)
created_at — TIMESTAMPTZ
RLS: Client: own goals. RM: assigned client goals.

Communication & Audit Tables

MESSAGES
message_id — PK, UUID
thread_id — UUID NOT NULL (per client-RM pair)
sender_type — ENUM (client, rm)
sender_id — UUID
content_encrypted — BYTEA (AES-256-GCM, E2E)
attachments — JSONB[]
read_at — TIMESTAMPTZ
created_at — TIMESTAMPTZ DEFAULT now()
RLS: Client: own threads. RM: threads with assigned clients. E2E encrypted — server cannot read.
DOCUMENT_VAULT
doc_id — PK, UUID
client_id — FK → clients
uploaded_by — UUID
doc_type — ENUM (cas_statement, tax_report, agreement, kyc, other)
doc_name — TEXT
storage_path — TEXT (Supabase Storage)
checksum — TEXT (SHA-256)
is_signed — BOOLEAN DEFAULT false
expiry_date — DATE
audit_trail — JSONB
created_at — TIMESTAMPTZ
RLS: Client: own documents. RM: assigned client documents.
AUDIT_LOG
log_id — PK, UUID
actor_type — ENUM (client, rm, system, cron)
actor_id — UUID
action — TEXT NOT NULL
entity_type — TEXT
entity_id — UUID
payload — JSONB
ip_address — INET
created_at — TIMESTAMPTZ DEFAULT now()
RLS: APPEND-ONLY. No UPDATE, no DELETE — ever. RM Admin: read team logs. Compliance: read all.

Key Relationships

clients.rm_idrelationship_managers.rm_id
custodian_accounts.client_idclients.client_id
holdings.account_idcustodian_accounts.account_id
transactions.holding_idholdings.holding_id
behavioral_signals.client_idclients.client_id
rm_context_notes.rm_idrelationship_managers.rm_id
context_snapshots.client_idclients.client_id
client_goals.client_idclients.client_id
07

The Flywheel

Why this gets better with every client interaction

The Intelligence Graph is not static. Every interaction enriches it. Better data produces better context. Better context produces better RM behavior. Better RM behavior produces better client experience. Better client experience produces more engagement. More engagement produces more behavioral signals. The loop accelerates.

1
Client uses the dashboard
Views portfolio, checks a holding, searches for something, exports a PDF. Normal usage.
2
Behavioral signals captured
trackPageView, trackHoldingCheck, trackSearchQuery fire silently. Signals stored with full context.
3
Intelligence Graph updated
Behavioral signals join hard data (custodians) and RM context (notes). The per-client model grows richer.
4
AI detects patterns
detectAnxietyCluster, matchHistoricalPattern, scoreEngagement run on the graph. Patterns surface that humans would miss.
5
RM receives context briefing
Not instructions. Context. The RM's judgment + synthesized context = better action than either alone.
6
RM acts with better insight
Calls at the right time. Says the right thing. Anticipates needs. Post-meeting notes feed back into the graph.
7
Client gets better service
Feels understood. Trusts the RM more. Uses the dashboard more. The cycle accelerates.
The Business Case
30–40
Clients per RM today
80–90
Clients per RM with Jugalbandi

Avg AUM ~50Cr per client. Each RM manages ~4,250Cr instead of ~2,000Cr. Revenue per RM more than doubles. Client NPS stays flat or improves.