Skip to content

Instantly share code, notes, and snippets.

@nhapentor
Last active October 19, 2025 14:16
Show Gist options
  • Select an option

  • Save nhapentor/a84f86685be78bceb1b0c25131b3921c to your computer and use it in GitHub Desktop.

Select an option

Save nhapentor/a84f86685be78bceb1b0c25131b3921c to your computer and use it in GitHub Desktop.
Banking Modernization Initiative
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml
LAYOUT_WITH_LEGEND()
title C1 System Context - Mobile Banking Platform
Person(customer, "Customer", "Manages finances via mobile/web")
Person(family, "Family/Friends", "Shared budgets and goals")
Person(agent, "Support Agent", "Handles escalations")
System(platform, "Mobile Banking Platform", "Intelligent financial co-pilot\nReal-time insights, budgets, goals, AI assistant\n<<PII+PCI>> <<Multi-AZ>>")
System_Ext(core, "Core Banking", "Accounts, transactions, payments")
System_Ext(payment, "Payment Rails", "ITMX, BAHTNET, Cards\n<<PCI>>")
System_Ext(idp, "Identity Provider", "OIDC/OAuth2, MFA, SCA")
System_Ext(llm, "AI Platform", "GPT-4o/Claude\nRAG, embeddings")
System_Ext(notification, "Notification Gateway", "Push, Email, SMS")
System_Ext(crm, "CRM/Contact Center", "Escalations, support")
Rel(customer, platform, "Uses", "HTTPS/Mobile")
Rel(family, platform, "Collaborates", "HTTPS")
Rel(agent, crm, "Works in", "SSO")
Rel(core, platform, "Transaction stream", "Kafka CDC")
Rel(platform, core, "Queries, payments", "REST/MTLS")
Rel(platform, payment, "Execute transfers", "ISO 20022")
Rel(platform, idp, "Auth/SCA", "OIDC")
Rel(platform, llm, "AI queries", "HTTPS/Streaming")
Rel(platform, notification, "Alerts", "REST")
Rel(platform, crm, "Escalate", "REST")
note right of platform
**Features:**
1. Real-time spending insights
2. Set up and track budgets in real-time
3. Savings goals and visualization
4. Shared budgets/goals
5. AI chatbot assistant
**SLA:** RPO=0, RTO≤4hr
end note
@enduml
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
LAYOUT_TOP_DOWN()
title C2 Container Diagram - Mobile Banking Platform
Person(customer, "Customer")
Person(family, "Family/Friends")
System_Boundary(platform, "Mobile Banking Platform") {
' Client Tier
Container(mobileapp, "Mobile App", "Swift/Kotlin", "iOS/Android")
' Gateway & Security
Container(apigw, "API Gateway", "Kong", "Rate limit, routing, MTLS")
Container(ciam, "Auth Service", "Keycloak", "OIDC/OAuth2, MFA/SCA\n<<PII>>")
' Feature Services
Container(insights, "Insights Service", "Python", "F1: Real-time analytics\nML categorization, patterns")
Container(budget, "Budget Service", "Java", "F2: Interactive budgets\nAuto-updates, alerts")
Container(goal, "Goal Service", "Java", "F3: Savings goals\nProgress tracking, milestones")
Container(collab, "Collaboration Service", "Java", "F4: Shared budgets/goals\nPermissions, sync")
Container(chatbot, "AI Chatbot", "FastAPI", "F5: Virtual assistant\nNLU, RAG, tool calls")
' Core Platform
Container(ledger, "Ledger Service", "Java", "Double-entry accounting\nImmutable journal\n<<PCI>>")
Container(notif, "Notification Service", "Node.js", "Multi-channel alerts")
' Data Layer
ContainerDb(appdb, "Application DBs", "PostgreSQL HA", "User, Budget, Goal data\n<<Multi-AZ, sync repl>>")
ContainerDb(ledgerdb, "Ledger DB", "PostgreSQL WORM", "Immutable entries\n<<PCI>>")
Container(eventbus, "Event Bus", "Kafka", "Transaction streams\nDomain events")
Container(cache, "Cache", "Redis Cluster", "Sessions, hot data")
' Supporting
Container(vault, "Secrets Vault", "Vault+HSM", "Keys, credentials")
Container(observability, "Observability", "ELK/Prometheus", "Logs, metrics, traces")
}
System_Ext(core, "Core Banking")
System_Ext(payment, "Payment Rails")
System_Ext(llm, "AI Platform")
System_Ext(pushgw, "Push Gateway")
' User flows
Rel(customer, mobileapp, "Uses", "HTTPS")
Rel(family, mobileapp, "Collaborates", "HTTPS")
' Gateway
Rel(mobileapp, apigw, "API calls", "HTTPS/JWT")
Rel(apigw, ciam, "Auth/AuthZ", "gRPC")
' Feature services
Rel(apigw, insights, "GET insights", "gRPC")
Rel(apigw, budget, "Budget ops", "gRPC")
Rel(apigw, goal, "Goal ops", "gRPC")
Rel(apigw, collab, "Shared ops", "gRPC")
Rel(apigw, chatbot, "Chat", "gRPC/Stream")
' Data flows
Rel(core, eventbus, "Transaction feed", "CDC")
Rel(eventbus, insights, "Consume txns", "Kafka")
Rel(eventbus, budget, "Consume txns", "Kafka")
Rel(insights, appdb, "Store", "SQL")
Rel(budget, appdb, "CRUD", "SQL")
Rel(goal, appdb, "CRUD", "SQL")
Rel(collab, appdb, "CRUD", "SQL")
Rel(budget, eventbus, "Publish budget.*", "Kafka")
Rel(goal, eventbus, "Publish goal.*", "Kafka")
Rel(goal, ledger, "Transfer funds", "gRPC")
Rel(ledger, ledgerdb, "Append-only", "SQL")
Rel(ledger, payment, "Execute payments", "ISO 20022")
Rel(chatbot, llm, "LLM inference", "HTTPS")
Rel(chatbot, budget, "Check budget", "gRPC")
Rel(chatbot, goal, "Check goal", "gRPC")
Rel(eventbus, notif, "Consume events", "Kafka")
Rel(notif, pushgw, "Send", "REST")
Rel(vault, chatbot, "API keys", "Dynamic secrets")
Rel(observability, apigw, "Collect", "Logs/Metrics")
note right of appdb
**HA Strategy:**
Multi-AZ sync replication
RPO: 0
RTO: <4HR
Backups: PITR
end note
@enduml
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
LAYOUT_TOP_DOWN()
title C3 Component Diagram - AI Chatbot Service (Feature 5)
Container_Boundary(chatbot, "AI Chatbot Service") {
Component(api, "Chatbot API", "FastAPI", "REST + WebSocket\nStreaming responses")
Component(nlu, "NLU Engine", "spaCy", "Intent classification\nEntity extraction")
Component(router, "Intent Router", "Rules", "Route: query/transaction/support")
Component(context, "Context Manager", "Redis", "Conversation history\n10-turn window")
Component(rag, "RAG Engine", "LangChain", "Vector search\nPrompt assembly")
Component(guard_pre, "Pre-Guardrails", "Custom", "PII masking\nToxicity filter")
Component(llm_gateway, "LLM Gateway", "Load balancer", "GPT-4o primary\nClaude fallback")
Component(guard_post, "Post-Guardrails", "Validators", "Hallucination check\nConfidence scoring")
Component(tool_orch, "Tool Orchestrator", "Workflow", "Budget/Goal/Payment tools\nParallel execution")
Component(escalation, "Escalation Handler", "REST client", "Low confidence → CRM\nTranscript export")
Component(audit, "Audit Logger", "Async", "GDPR compliance\nAll queries logged")
}
ContainerDb(vectordb, "Vector DB", "Pinecone", "Embeddings\nKnowledge base")
ContainerDb(chatdb, "Chat History", "PostgreSQL", "Conversations\n<<PII>>")
Container(cache, "Redis", "Cache", "Context + sessions")
System_Ext(llm_gpt, "OpenAI GPT-4o", "Primary LLM")
System_Ext(llm_claude, "Anthropic Claude", "Fallback LLM")
Container(budget_svc, "Budget Service", "Tool")
Container(goal_svc, "Goal Service", "Tool")
Container(ledger_svc, "Ledger Service", "Tool")
System_Ext(crm, "CRM", "Escalation")
Rel(api, nlu, "Extract intent")
Rel(api, context, "Fetch history")
Rel(nlu, router, "Route")
Rel(router, guard_pre, "Sanitize")
Rel(guard_pre, rag, "Retrieve context")
Rel(rag, vectordb, "Search")
Rel(guard_pre, llm_gateway, "Generate")
Rel(llm_gateway, llm_gpt, "Primary")
Rel(llm_gateway, llm_claude, "Fallback")
Rel(llm_gateway, guard_post, "Validate")
Rel(guard_post, tool_orch, "Execute tools")
Rel(tool_orch, budget_svc, "Check budget")
Rel(tool_orch, goal_svc, "Check goal")
Rel(tool_orch, ledger_svc, "Init payment + SCA")
Rel(guard_post, escalation, "If confidence <70%")
Rel(escalation, crm, "Handoff")
Rel(api, audit, "Log all interactions")
Rel(api, chatdb, "Persist")
note right of llm_gateway
**Model Selection:**
GPT-4o: Complex reasoning
Claude: Speed-critical queries
end note
note right of guard_pre
**Pre-Guardrails:**
• PII detection & masking
• Toxicity filter
• Jailbreak detection
end note
note right of guard_post
**Post-Guardrails:**
• Hallucination detection
• Confidence scoring
• Escalate to agent
• PII leak prevention
end note
@enduml
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
title C3 Standard Microservice Pattern\nApplied to: Budget, Goal, Collaboration, Analytics Services
Container_Boundary(service, "Generic Microservice (Budget/Goal/Collab/Analytics)") {
Component(api, "API Layer", "REST/gRPC", "Endpoints\nValidation\nIdempotency")
Component(domain, "Domain Logic", "Business rules", "Core logic\nValidation\nOrchestration")
Component(event_pub, "Event Publisher", "Kafka producer", "Publish domain events\nAsync notifications")
Component(repo, "Repository", "Data access", "CRUD operations\nOptimistic locking (CAS)")
Component(cache, "Cache Layer", "Redis wrapper", "Hot data")
}
ContainerDb(db, "Service Database", "PostgreSQL", "Owned schema\nHA replicas")
Container(eventbus, "Event Bus", "Kafka", "Domain events")
Container(redis, "Redis", "Cache", "Shared cluster")
Rel(api, domain, "Delegate")
Rel(domain, repo, "Persist")
Rel(repo, db, "SQL/TLS")
Rel(repo, cache, "Cache")
Rel(cache, redis, "GET/SET")
Rel(domain, event_pub, "Publish events")
Rel(event_pub, eventbus, "Produce")
note right of service
**Pattern Applied To:**
**Budget Service:**
• Domain: Budget creation, threshold checks
• Events: budget.updated, budget.threshold_hit
• Database: budgets, budget_history
**Goal Service:**
• Domain: Goal creation, milestone tracking
• Events: goal.contributed, goal.milestone.reached
• Database: goals, contributions, milestones
**Collaboration Service:**
• Domain: Permissions (RBAC), fairness tracking
• Events: collab.user.joined, collab.user.left
• Database: shared_budgets, shared_goals, permissions
**Analytics Service:**
• Domain: ML categorization, pattern detection
• Events: txn.categorized, insights.generated
• Database: categorized_txns, patterns
**Common Patterns:**
• Event-driven updates
• Optimistic locking (version field)
• Cache-aside pattern
• Idempotency via UUID keys
end note
@enduml
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Deployment.puml
LAYOUT_LANDSCAPE()
title Deployment Diagram - Mobile Banking Platform\nMulti-AZ Active-Active | RPO=0, RTO≤4hr
' Client Layer
Deployment_Node(mobile, "Mobile Devices", "iOS/Android") {
Container(mobile_app, "Mobile App", "Swift/Kotlin")
}
' Primary Region
Deployment_Node(primary_region, "Primary Region", "Production") {
Deployment_Node(multi_az, "Multi-AZ Deployment", "3 Availability Zones") {
' Application Tier
Deployment_Node(app_tier, "Application Tier", "Kubernetes") {
Container(services, "Microservices", "API Gateway\nFeature Services\n(Budget, Goal, Collab, AI)\nLedger, Notifications", "Auto-scaling\n3-20 replicas/service")
}
' Data Tier
Deployment_Node(data_tier, "Data Tier", "Managed Services") {
ContainerDb(postgres, "PostgreSQL Cluster", "Primary + 2 Replicas\nSync replication\nAuto-failover <5min", "<<Multi-AZ>>\n<<PII+PCI>>")
Container(kafka, "Kafka Cluster", "3 brokers\nRF=3, Min ISR=2", "Event streaming")
Container(redis, "Redis Cluster", "Master + replicas\nHA mode", "Cache + sessions")
}
' Shared Services
Deployment_Node(shared, "Cross-AZ Services", "Region-wide") {
Container(vault, "Secrets Vault", "HashiCorp Vault\nHSM-backed", "3-node HA")
Container(s3, "Object Storage", "S3\nBackups + logs", "PITR every 5min\n7-year retention")
Container(monitoring, "Observability", "Prometheus\nELK\nJaeger", "Metrics, logs, traces")
}
}
}
' DR Region
Deployment_Node(dr_region, "DR Region", "Passive Standby") {
Deployment_Node(dr_infra, "Warm Standby", "Scaled down") {
Container(dr_services, "Services", "1 replica/service\nActivate on failover")
ContainerDb(dr_db, "PostgreSQL Replica", "Async replication\nRPO ~5min")
Container(dr_storage, "S3 Backup", "Cross-region replication")
}
}
' External Systems
Deployment_Node(external, "External Systems", "Third-Party") {
System_Ext(core_banking, "Core Banking", "VPN")
System_Ext(payment_rails, "Payment Rails", "MTLS")
System_Ext(ai_platform, "AI Platform", "HTTPS")
}
' Relationships
Rel(mobile_app, services, "HTTPS", "Load balanced")
Rel(services, postgres, "SQL/TLS", "Read/Write")
Rel(services, kafka, "Produce/Consume", "Events")
Rel(services, redis, "Cache", "Session data")
Rel(services, vault, "Secrets", "Dynamic credentials")
Rel(postgres, s3, "Backup", "PITR + WAL")
Rel(postgres, dr_db, "Async Replication", "Cross-region")
Rel(s3, dr_storage, "Replication", "Automated")
Rel(services, core_banking, "MTLS", "VPN tunnel")
Rel(services, payment_rails, "ISO 20022", "Dedicated network")
Rel(services, ai_platform, "HTTPS", "API calls")
' Strategic Notes
note right of multi_az
**High Availability Strategy:**
• Active-active across 3 AZs
• Load balancing: Round-robin + health checks
**RPO = 0:**
• Synchronous replication (quorum: 2/3 AZs)
• No data loss on AZ failure
**RTO:**
• Auto-failover for databases
• Stateless services (instant recovery)
end note
note right of dr_region
**Disaster Recovery Strategy:**
**RTO ≤ 4 hours:**
1. Detection: automated monitoring
2. Decision: runbook
3. DNS cutover
4. Service scale-up
5. DB promotion
6. Validation
**RPO = 0:**
• Synchronous cross-region replication (latency)
**Warm Standby:**
• Services running at minimum capacity
• Database replica ready for promotion
• Manual activation trigger
end note
note right of shared
**Cross-Cutting Concerns:**
**Security:**
• Zero-trust architecture
• mTLS between all services
• HSM for key management
• VPC isolation (public/private/data subnets)
**Compliance:**
• PII/PCI data segregation
• Audit logs
• Encryption at rest & in transit
• PITR backups
**Observability:**
• Full-stack monitoring
• SLO tracking
• Distributed tracing
• Automated alerting
end note
@enduml
@startuml
!theme plain
title Data Flow Diagram - Real-Time Spending Insights with Budgeting Tool (Feature 1)\nData Movement & Transformations
' Define entities
rectangle "Customer" as Customer <<External Entity>>
rectangle "Tesco Lotus\n(Merchant)" as Merchant <<External Entity>>
' Define processes
rectangle "1.0\nPromptPay\nPayment Processing" as P1 <<Process>>
rectangle "2.0\nTransaction\nCategorization" as P2 <<Process>>
rectangle "3.0\nBudget\nUpdate & Analysis" as P3 <<Process>>
rectangle "4.0\nInsight\nGeneration" as P4 <<Process>>
rectangle "5.0\nNotification\nDelivery" as P5 <<Process>>
' Define data stores
database "D1\nTransaction\nLedger" as D1 <<Data Store>>
database "D2\nCategorized\nTransactions" as D2 <<Data Store>>
database "D3\nBudget\nDatabase" as D3 <<Data Store>>
database "D4\nML Model\nStore" as D4 <<Data Store>>
database "D5\nUser\nPreferences\n<<PII>>" as D5 <<Data Store>>
' External system
rectangle "Core Banking\nSystem" as CoreBank <<External System>>
rectangle "Push Gateway" as PushGW <<External System>>
' Data flows - Customer to System
Customer --> P1: "Scan QR code\n(merchant_id, amount: ฿1,500)"
P1 --> Customer: "Payment confirmation\n(txn_id, status)"
' Process 1: Payment Processing
P1 --> CoreBank: "Payment instruction\n(from_account, to_merchant,\namount, idempotency_key)\n<<MTLS>>"
CoreBank --> P1: "Payment result\n(txn_id, status: COMPLETED)"
P1 --> D1: "Store transaction\n(txn_id, user_id, amount,\nmerchant, timestamp)\n<<Immutable>>"
P1 --> P2: "Transaction event\n(txn_id, user_id: USR-789,\namount: 1500, merchant: 'Tesco Lotus',\nMCC: 5411)\n<<Kafka: transaction.posted>>"
' Process 2: Categorization
D4 --> P2: "ML model weights"
P2 --> P2: "Apply ML model\nInput: merchant + MCC\nOutput: category + confidence"
P2 --> D2: "Store categorized txn\n(txn_id, category: 'Groceries',\nconfidence: 96%)"
P2 --> P3: "Categorized event\n(txn_id, user_id, amount: 1500,\ncategory: 'Groceries')\n<<Kafka: txn.categorized>>"
' Process 3: Budget Update
D3 --> P3: "Read current budget\n(category: Groceries,\nlimit: 16000, spent: 13500)"
P3 --> P3: "Calculate new balance\nspent = 13500 + 1500 = 15000\npct = 15000/16000 = 93.75%\nCheck threshold: 93.75% ≥ 90%"
P3 --> D3: "Update budget\n(spent: 15000, pct: 93.75%,\nthreshold_hit: true)\n<<Optimistic lock>>"
P3 --> P4: "Budget status\n(budget_id, category, spent,\nremaining:
@startuml
!theme plain
title Data Flow Diagram - Shared Budgets and Real-Time Sync (Feature 4)\nMulti-User Data Flow & Collaboration
' Define entities
rectangle "User A\n(Owner)" as UserA <<External Entity>>
rectangle "User B\n(Contributor)" as UserB <<External Entity>>
' Define processes
rectangle "1.0\nShared Budget\nAccess Control" as P1 <<Process>>
rectangle "2.0\nPayment\nProcessing" as P2 <<Process>>
rectangle "3.0\nShared Budget\nUpdate" as P3 <<Process>>
rectangle "4.0\nReal-Time\nSync Distribution" as P4 <<Process>>
rectangle "5.0\nNotification\nFormatting" as P5 <<Process>>
' Define data stores
database "D1\nCollaboration\nDatabase\n<<PII>>" as D1 <<Data Store>>
database "D2\nShared Budget\nDatabase" as D2 <<Data Store>>
database "D3\nTransaction\nHistory" as D3 <<Data Store>>
database "D4\nWebSocket\nSession Store" as D4 <<Data Store>>
' External systems
rectangle "Core Banking\nSystem" as CoreBank <<External System>>
rectangle "Push Gateway" as PushGW <<External System>>
' Data flows - User A (Owner)
UserA --> P1: "Access shared budget\n(budget_id: BDG-456,\nuser_id: A)\n<<JWT token>>"
P1 --> D1: "Check permissions\n(user: A, budget: BDG-456)"
D1 --> P1: "Role: Owner\nPermissions: [read, write,\nmanage_users, edit_limit]"
P1 --> D2: "Read budget data\n(budget_id: BDG-456)"
D2 --> P1: "Budget details\n(limit: 16000, spent: 13500,\nparticipants: [A, B])"
P1 --> UserA: "Budget view + permissions\n(spent: ฿13,500 / ฿16,000,\n84.4%)"
' WebSocket connection - User A
UserA --> P4: "WebSocket CONNECT\n(user: A, budget: BDG-456)"
P4 --> D4: "Store session\n(user: A, budget: BDG-456,\nconnection_id, status: online)"
D4 --> P4: "Session registered"
' Data flows - User B (Contributor)
UserB --> P1: "Access shared budget\n(budget_id: BDG-456,\nuser_id: B)\n<<JWT token>>"
P1 --> D1: "Check permissions\n(user: B, budget: BDG-456)"
D1 --> P1: "Role: Contributor\nPermissions: [read, spend]"
P1 --> D2: "Read budget data"
D2 --> P1: "Same budget details"
P1 --> UserB: "Budget view\n(spent: ฿13,500 / ฿16,000)"
' WebSocket connection - User B
UserB --> P4: "WebSocket CONNECT\n(user: B, budget: BDG-456)"
P4 --> D4: "Store session\n(user: B, status: online)"
' Payment flow - User B
UserB --> P2: "Make purchase\n(amount: 1800,\nmerchant: 'Tesco Lotus',\nbudget_id: BDG-456)\n<<JWT token>>"
P2 --> D1: "Verify spend permission\n(user: B, budget: BDG-456)"
D1 --> P2: "Role: Contributor\nCan spend: YES"
P2 --> CoreBank: "Execute payment\n(amount: 1800,\nfrom: UserB_account,\nidempotency_key)\n<<MTLS>>"
CoreBank --> P2: "Payment confirmed\n(txn_id: TXN-12345)"
' Budget update
P2 --> P3: "Payment event\n(user: B, budget: BDG-456,\namount: 1800, merchant)\n<<Kafka: payment.completed>>"
P3 --> D2: "Read current budget\n(budget_id: BDG-456)\n<<FOR UPDATE>>"
D2 --> P3: "Current state\n(spent: 13500, version: 42)"
P3 --> P3: "Calculate update\nnew_spent = 13500 + 1800 = 15300\nnew_pct = 15300/16000 = 95.6%\nCheck: 95.6% ≥ 90% threshold\n→ ALERT triggered"
P3 --> D2: "Update budget\nSET spent = 15300,\npct = 95.6%,\nversion = 43\nWHERE version = 42\n<<Optimistic lock>>"
P3 --> D3: "Log transaction\n(budget_id, user: B,\namount: 1800, timestamp,\nattribution: 'User B')"
' Real-time sync
P3 --> P4: "Budget update event\n(budget_id: BDG-456,\nuser: B, amount: 1800,\nnew_spent: 15300, new_pct: 95.6%,\nthreshold_hit: true)\n<<Kafka: budget.updated>>"
P4 --> D1: "Get all participants\n(budget_id: BDG-456)"
D1 --> P4: "Participants: [A, B]\nwith roles"
P4 --> D4: "Check online status\n(users: [A, B])"
D4 --> P4: "Online: [A, B]\nConnection IDs"
P4 --> P4: "Build sync message\n{type: 'budget_update',\nuser: 'User B',\nmerchant: 'Tesco Lotus',\namount: 1800,\nnew_spent: 15300,\nnew_pct: 95.6%,\nalert: true}"
' WebSocket broadcast
P4 --> UserA: "WebSocket PUSH\n<<Real-time update>>\n'User B spent ฿1,800\nat Tesco Lotus.\n95.6% of budget used.'"
P4 --> UserB: "WebSocket PUSH\n<<Confirmation>>\n'Your purchase updated\nshared budget.'"
' Notification formatting
P4 --> P5: "Alert notification\n(participants: [A, B],\nbudget_update, threshold_hit)"
P5 --> P5: "Format notification\nfor each user role:\n- Owner: Full alert\n- Contributor: Confirmation"
P5 --> PushGW: "Push payload\n(users: [A, B],\ntitle, body, data)"
' User feedback
UserA --> P1: "View updated budget\n(refresh)"
P1 --> D3: "Read transaction history\n(budget_id: BDG-456,\nORDER BY timestamp DESC)"
D3 --> P1: "Recent transactions\n[{user: B, amount: 1800,\ntimestamp, merchant}]"
P1 --> UserA: "Transaction log\n'User B: ฿1,800\nat Tesco Lotus'"
UserB --> P1: "View contribution tracking"
P1 --> D3: "Query user contributions\n(budget_id: BDG-456,\nuser_id: B)"
D3 --> P1: "User B total: ฿8,300\n(54% of total spent)"
P1 --> UserB: "Your contribution: ฿8,300"
' Legend
note right of D1
**Collaboration Data:**
• Budget sharing relationships
• User roles & permissions
• Participant lists
**Roles:**
- Owner: Full control
- Contributor: Can spend
- Viewer: Read-only (not shown)
**Data Security:**
<<PII>> - User relationships
Encrypted at rest
Row-level access control
end note
note bottom
**Key Data Flows:**
1. Access Control: JWT → Role check → Permission validation
2. Payment: User B → Permission check → Core Banking → Transaction
3. Budget Update: Transaction → Calculate → Update (CAS) → Event
4. Real-Time Sync: Event → Get participants → Check online → WebSocket broadcast
5. Transaction Attribution: All changes logged with user attribution
**Data Consistency:**
• Optimistic locking (version field) prevents race conditions
• Event-driven updates ensure all participants see same state
• WebSocket for online users (<100ms), Push for offline
• Transaction history maintains full audit trail
**Collaboration Features:**
• Multi-user read/write access with RBAC
• Real-time synchronization via WebSocket
• Transaction attribution (who spent what)
• Contribution tracking per user
• Fair share calculations (optional)
end note
@enduml
@startuml
!theme plain
skinparam responseMessageBelowArrow true
title Sequence Diagram - Real-Time Spending Insights (Feature 1)\nPromptPay QR Payment to Real-Time Budget Alert
actor Customer
participant "Mobile App" as App
participant "API Gateway" as APIGW
participant "Payment\nService" as Payment
participant "Core Banking" as Core
participant "Event Bus\n(Kafka)" as Kafka
participant "Analytics\nService" as Analytics
participant "Budget\nService" as Budget
participant "Notification\nService" as Notif
participant "Push Gateway" as Push
database "Analytics DB" as AnalyticsDB
database "Budget DB" as BudgetDB
Customer -> App: Scan PromptPay QR code\nat Tesco Lotus
activate App
App -> App: Parse QR code\nMerchant ID, Amount: ฿1,500
App -> APIGW: POST /payments/promptpay\n{merchant_id, amount: 1500,\nuser_account}\nJWT token
activate APIGW
APIGW -> APIGW: Validate JWT\nCheck permissions
APIGW -> Payment: Initiate PromptPay transfer\n{from_account, to_merchant, amount}
activate Payment
Payment -> Core: Execute payment\nPromptPay network\nMTLS + Idempotency key
activate Core
Core -> Core: Process transaction\nDebit account ฿1,500\nCredit merchant
Core -> Kafka: Publish event\ntransaction.posted\n{user_id: USR-789,\namount: 1500.00,\nmerchant: "Tesco Lotus",\nMCC: 5411,\npayment_method: "PromptPay"}
activate Kafka
Core --> Payment: Payment confirmed\n{txn_id: TXN-12345}
deactivate Core
Payment --> APIGW: 201 Created\n{txn_id, status: COMPLETED}
deactivate Payment
APIGW --> App: Payment successful
deactivate APIGW
App --> Customer: "Payment completed!\n฿1,500 paid to Tesco Lotus"
deactivate App
note over Kafka
Event contains:
• User ID (partition key)
• Amount: ฿1,500
• Merchant: "Tesco Lotus"
• MCC: 5411 (Grocery stores)
• Payment method: PromptPay
• Timestamp
end note
Kafka -> Analytics: Consume event\ntransaction.posted
activate Analytics
Analytics -> Analytics: ML Categorization\nMerchant: "Tesco Lotus"\nMCC: 5411\n→ Category: "Groceries"\nConfidence: 96%
Analytics -> AnalyticsDB: INSERT categorized_transaction\n{txn_id, category: "Groceries",\nconfidence: 0.96}
activate AnalyticsDB
AnalyticsDB --> Analytics: OK
deactivate AnalyticsDB
Analytics -> Kafka: Publish event\ntxn.categorized\n{txn_id: TXN-12345,\nuser_id: USR-789,\ncategory: "Groceries",\namount: 1500.00}
deactivate Analytics
Kafka -> Budget: Consume event\ntxn.categorized
activate Budget
Budget -> BudgetDB: UPDATE budgets\nSET spent = spent + 1500\nWHERE user_id = 'USR-789'\nAND category = 'Groceries'
activate BudgetDB
BudgetDB -> BudgetDB: Calculate\nOld: spent = ฿13,500\nNew: spent = ฿15,000\nLimit: ฿16,000\nPct used: 93.75%
BudgetDB --> Budget: Updated\n{spent: 15000, limit: 16000,\nremaining: 1000, pct: 93.75%}
deactivate BudgetDB
Budget -> Budget: Check threshold\n93.75% ≥ 90% alert level\n→ TRIGGER ALERT
Budget -> Kafka: Publish event\nbudget.threshold_hit\n{user_id: USR-789,\ncategory: "Groceries",\npct_used: 93.75%,\nremaining: 1000,\ndays_left: 12}
deactivate Budget
Kafka -> Notif: Consume event\nbudget.threshold_hit
activate Notif
Notif -> Notif: Build notification message\n" You just spent ฿1,500 at Tesco Lotus.\nThat's 93.75% of your grocery budget!\nOnly ฿1,000 left for 12 days."
Notif -> Push: POST /push\n{user_id, title, body, data}
activate Push
Push -> Push: Route to device\nFCM (Android) or APNs (iOS)
Push --> Customer: Push notification\n" 93.75% of grocery\nbudget spent"
Push --> Notif: 200 OK\n{message_id}
deactivate Push
Notif -> Kafka: Publish event\nnotification.sent\n{user_id, type: "budget_alert",\nchannel: "push"}
deactivate Notif
Customer -> App: Tap notification
activate App
App -> APIGW: GET /insights/latest
activate APIGW
APIGW -> Analytics: GET /insights?user_id=USR-789
activate Analytics
Analytics -> AnalyticsDB: SELECT insights\nWHERE user_id = 'USR-789'\nORDER BY timestamp DESC\nLIMIT 1
activate AnalyticsDB
AnalyticsDB --> Analytics: Return latest insight
deactivate AnalyticsDB
Analytics --> APIGW: {insights: [\n"93.75% of grocery budget used",\n"฿1,000 remaining for 12 days",\n"At current rate, runs out in 4 days"\n]}
deactivate Analytics
APIGW --> App: 200 OK\n{insights, budget_status}
deactivate APIGW
App -> App: Render dashboard\n- Progress bar: 93.75% (red)\n- Remaining: ฿1,000\n- Runway: 4 days
App --> Customer: Display insight with\nvisual progress indicator
deactivate App
note over Customer
**User Experience:**
1. Scan QR at Tesco Lotus
2. Confirm payment (฿1,500)
3. Receive instant confirmation
4. Get real-time budget alert
5. View detailed spending insight
end note
@enduml
@startuml
!theme plain
skinparam responseMessageBelowArrow true
title Sequence Diagram - Shared Budget Real-Time Sync (Feature 4)\nMulti-User Collaboration | Real-Time Updates
actor "User A\n(Owner)" as UserA
actor "User B\n(Contributor)" as UserB
participant "Mobile App A" as AppA
participant "Mobile App B" as AppB
participant "API Gateway" as APIGW
participant "Budget\nService" as Budget
participant "Collaboration\nService" as Collab
participant "Event Bus\n(Kafka)" as Kafka
participant "Sync Engine\n(WebSocket)" as Sync
database "Budget DB" as BudgetDB
database "Collab DB" as CollabDB
note over UserA, CollabDB
**Shared Budget: "Household Groceries"**
Monthly Limit: ฿16,000
Current Spent: ฿13,500 (84.4%)
Participants: User A (Owner), User B (Contributor)
end note
UserA -> AppA: Open "Household Groceries"\nshared budget
activate AppA
AppA -> APIGW: GET /budgets/BDG-456\nJWT token
activate APIGW
APIGW -> Budget: GET /budgets/BDG-456
activate Budget
Budget -> BudgetDB: SELECT budget\n+ participants
activate BudgetDB
BudgetDB --> Budget: {limit: 16000,\nspent: 13500,\nparticipants: [A, B]}
deactivate BudgetDB
Budget --> APIGW: Budget data
deactivate Budget
APIGW --> AppA: 200 OK
deactivate APIGW
AppA -> APIGW: WebSocket CONNECT
activate APIGW
APIGW -> Sync: Register connection\n{user: A, budget: BDG-456}
activate Sync
Sync --> APIGW: Connected
deactivate Sync
deactivate APIGW
AppA --> UserA: Dashboard displayed\nSpent: ฿13,500 / ฿16,000\n(84.4%)
deactivate AppA
UserB -> AppB: Open same shared budget
activate AppB
AppB -> APIGW: GET /budgets/BDG-456\n+ WebSocket CONNECT
activate APIGW
APIGW --> AppB: Budget data + Connected\n"User A is online"
deactivate APIGW
AppB --> UserB: Dashboard displayed\nSpent: ฿13,500 / ฿16,000
deactivate AppB
== User B Makes Purchase ==
UserB -> AppB: Scan PromptPay QR\nat Tesco Lotus\nAmount: ฿1,800
activate AppB
AppB -> APIGW: POST /payments/promptpay\n{merchant: "Tesco Lotus",\namount: 1800,\nbudget_id: BDG-456}\nJWT token
activate APIGW
APIGW -> Collab: Verify spend permission\n{user: B, budget: BDG-456}
activate Collab
Collab -> CollabDB: Check role
activate CollabDB
CollabDB --> Collab: Role: Contributor\nCan spend: YES
deactivate CollabDB
Collab --> APIGW: ✓ Authorized
deactivate Collab
APIGW -> Budget: Process payment
activate Budget
Budget -> BudgetDB: UPDATE budgets\nSET spent = spent + 1800
activate BudgetDB
BudgetDB -> BudgetDB: Calculate\nOld: ฿13,500 (84.4%)\nNew: ฿15,300 (95.6%)\n✓ Threshold crossed (90%)
BudgetDB --> Budget: Updated
deactivate BudgetDB
Budget -> Kafka: Publish event\nbudget.updated\n{budget_id: BDG-456,\nuser_id: B,\namount: 1800,\nnew_spent: 15300,\nnew_pct: 95.6%,\nthreshold_hit: true}
activate Kafka
Budget --> APIGW: 200 OK\n{new_balance,\nthreshold_alert: true}
deactivate Budget
APIGW --> AppB: Payment successful
deactivate APIGW
AppB -> AppB: Update local view\nSpent: ฿15,300 (95.6%)\nShow alert: "95.6% used!"
AppB --> UserB: Payment confirmed\n+ budget warning
deactivate AppB
== Real-Time Sync to User A ==
Kafka -> Sync: Consume event\nbudget.updated
activate Sync
Sync -> Collab: Get participants\n{budget_id: BDG-456}
activate Collab
Collab -> CollabDB: SELECT participants
activate CollabDB
CollabDB --> Collab: [User A, User B]
deactivate CollabDB
Collab --> Sync: Participants list
deactivate Collab
Sync -> Sync: Build WebSocket message\n{type: "budget_update",\nuser: "User B",\nmerchant: "Tesco Lotus",\namount: 1800,\nnew_spent: 15300,\nnew_pct: 95.6%,\nalert: true}
Sync -> AppA: Push via WebSocket
activate AppA
AppA -> AppA: Real-time update\n- Progress: 84.4% → 95.6%\n- Amount: ฿13,500 → ฿15,300\n- Show alert: "User B spent\n ฿1,800 at Tesco Lotus.\n 95.6% of budget used!\n Only ฿700 remaining."
AppA --> UserA: Dashboard updated instantly
deactivate AppA
Sync -> AppB: Confirmation\n(already updated locally)
activate AppB
AppB --> UserB: "Shared budget updated"
deactivate AppB
Sync --> Kafka: Sync complete
deactivate Sync
note over UserA, UserB
**Real-Time Collaboration:**
**User A (Owner):**
• Sees User B's purchase instantly
• Gets budget alert notification
• Can manage budget limits & participants
**User B (Contributor):**
• Can make purchases from shared budget
• Sees immediate confirmation
• Updates visible to all participants
**Permission Enforcement:**
• API Gateway validates role before allowing spend
• Collaboration Service maintains access control
• Budget updates broadcast via WebSocket
end note
@enduml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment