# tinhnguyen0110/shb-digital architecture

> Architecture diagram of the GitHub repository tinhnguyen0110/shb-digital, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-07-31). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/tinhnguyen0110/shb-digital
- Repository: https://github.com/tinhnguyen0110/shb-digital

## Overview

#### 1. Purpose and entry points
Digital Expert Guild is a Vietnamese digital-bank workflow system: customers request lending/service assistance through chat; four AI domain specialists assess cases, retrieve bank data/policy, and execute controlled operations. Bank staff supervise approvals, audit, and metrics.

Runtime entry points:
- FastAPI application: `backend/app/main.py`
- React SPA bootstrap: `frontend/src/main.tsx`
- Docker deployment: `docker-compose.prod.yml`
- Benchmark runners: `bench/run_single.py`, `bench/run_multi.py`

#### 2. API, identity, and client boundary
The frontend communicates with FastAPI over REST and SSE, with cookie-based JWT authentication. Customer and bank/admin personas are authorization boundaries; APIs expose conversations, approvals, audit, stats, model selection, comparison, and live streams.

Key paths:
- `backend/app/api/conversations.py`
- `backend/app/auth/router.py`
- `backend/app/api/sse.py`
- `frontend/src/api/client.ts`
- `frontend/src/Workspace.tsx`

#### 3. Persistent banking state and provenance
PostgreSQL 15 is the system of record for banking entities, conversations/tasks/cards, approvals, audit records, retrieval data, and LLM cost metrics. SQLAlchemy/Alembic own schema evolution; seed modules populate an executable demo/lab dataset. The design deliberately keeps transactional business state and audit/projection state in one database.

Key paths:
- `backend/app/db/models.py`
- `backend/app/db/migrations/versions/`
- `backend/app/db/seed_from_lab.py`
- `deploy/seed/shb-132.db`

#### 4. Agent orchestration lifecycle
A chat request creates or resumes a durable MAIN agent session. MAIN plans work and dispatches independent role-specific SUB agents asynchronously; the orchestration shell tracks events, role/task state, retries/resumption, and wakes MAIN when work or approval decisions complete. It is not a fixed workflow graph: MAIN determines whether to wait, delegate, or synthesize.

Key paths:
- `backend/app/orch/main_session.py`
- `backend/app/orch/dispatch.py`
- `backend/app/orch/sub_runner.py`
- `backend/app/orch/room.py`

#### 5. Extensible specialist and retrieval boundary
Specialists are mounted from role directories rather than embedded in the orchestrator. Each supplies a skill prompt and Python business tools; the mount layer supplies schemas, database access, and scoped execution. Shared retrieval combines policy wiki/document lineage, vector notes, and related-entity checks, while numerical assessments use direct database tools.

Key paths:
- `backend/app/mount/mount_role.py`
- `roles/credit/SKILL.md`
- `roles/credit/functions.py`
- `roles/_retrieval/functions.py`
- `deploy/seed/wiki/`

#### 6. Controlled action and approval gate
Sensitive actions, notably disbursement, cross a server-side tool gate rather than relying on prompts. The gate normalizes payloads, creates or checks approval tickets, atomically claims approved actions, performs the underlying operation, and records a receipt in one transaction. Ownership checks and assessment verdicts can further deny or escalate actions. Admin decisions re-enter the orchestration lifecycle.

Key paths:
- `backend/app/orch/gated.py`
- `backend/app/orch/disburse_guard.py`
- `backend/app/orch/verdict.py`
- `backend/app/api/approvals.py`

#### 7. Observability and presentation flow
Agents emit messages, task changes, thinking/tool-call traces, cards, and approvals through an SSE bus; a single redaction boundary protects secrets before client delivery. The SPA renders chat, source-backed cards, a 3D specialist lobby, and the admin Control Tower. Audit is append-only; notifications can be in-app and optional Gmail email.

Key paths:
- `backend/app/sse/bus.py`
- `backend/app/sse/redact.py`
- `backend/app/orch/audit_emit.py`
- `frontend/src/components/ControlTower.tsx`
- `frontend/src/components/cards/CardRenderer.tsx`

#### 8. Runtime infrastructure and model providers
Backend is Python 3.11/FastAPI/uvicorn; frontend is React 19/Vite/TypeScript, served/proxied by nginx in production. Docker Compose runs PostgreSQL, backend, and frontend; cloudflared is part of deployed access. The agent runtime uses Claude Agent SDK with per-session provider configuration for Claude, GLM, GPT gateway, or local Ollama; provider keys remain server-side.

Key paths:
- `backend/pyproject.toml`
- `configs/providers.yaml`
- `backend/Dockerfile`
- `frontend/Dockerfile`
- `frontend/nginx.conf`

Main entry points: [`backend/app/main.py`](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/main.py) (FastAPI application), [`backend/app/orch/main_session.py`](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/orch/main_session.py) (MAIN session), [`backend/app/db/models.py`](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/db/models.py) (PostgreSQL system of record), [`docker-compose.prod.yml`](https://github.com/tinhnguyen0110/shb-digital/blob/master/docker-compose.prod.yml) (Production Compose)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Client &amp; staff"]
  node_spa["React workspace<br/>React SPA<br/>[Workspace.tsx]"]
  node_api_client["REST/SSE client<br/>TypeScript client<br/>[client.ts]"]
end

subgraph group_api["API &amp; identity"]
  node_fastapi["FastAPI application<br/>Python API<br/>[main.py]"]
  node_auth["Cookie JWT auth<br/>identity router<br/>[router.py]"]
  node_conversations["Conversation API<br/>chat router<br/>[conversations.py]"]
  node_approvals_api["Approval API<br/>admin router<br/>[approvals.py]"]
  node_sse_api["Live stream API<br/>SSE router<br/>[sse.py]"]
end

subgraph group_agents["Agent runtime"]
  node_main_session{{"MAIN session<br/>durable orchestrator<br/>[main_session.py]"}}
  node_dispatch["Role dispatch<br/>async dispatcher<br/>[dispatch.py]"]
  node_specialists["Specialist roles<br/>mounted agents<br/>[mount_role.py]"]
  node_retrieval["Policy retrieval<br/>shared tools<br/>[functions.py]"]
  node_action_gate{{"Controlled action gate<br/>transactional guard<br/>[gated.py]"}}
  node_sse_bus["Redacted event bus<br/>SSE bus<br/>[bus.py]"]
end

subgraph group_data["State &amp; knowledge"]
  node_postgres[("PostgreSQL system of record<br/>PostgreSQL 15<br/>[models.py]")]
  node_migrations["Schema migrations<br/>Alembic"]
  node_wiki_seed["Policy wiki seed<br/>knowledge corpus"]
end

subgraph group_ops["Deployment &amp; providers"]
  node_providers["Model providers<br/>provider configuration<br/>[providers.yaml]"]
  node_docker["Production Compose<br/>Docker deployment"]
  node_benchmarks["Benchmark runners<br/>evaluation CLI<br/>[run_multi.py]"]
end

node_spa -->|"uses"| node_api_client
node_api_client -->|"REST and SSE"| node_fastapi
node_fastapi -->|"authenticates"| node_auth
node_fastapi -->|"routes chat"| node_conversations
node_fastapi -->|"routes decisions"| node_approvals_api
node_fastapi -->|"routes streams"| node_sse_api
node_conversations -->|"creates or resumes"| node_main_session
node_approvals_api -->|"wakes on decision"| node_main_session
node_main_session -->|"delegates"| node_dispatch
node_dispatch -->|"runs roles"| node_specialists
node_specialists -->|"retrieves policy and entities"| node_retrieval
node_specialists -->|"requests sensitive actions"| node_action_gate
node_action_gate -->|"atomically updates"| node_postgres
node_main_session -->|"persists sessions and tasks"| node_postgres
node_retrieval -->|"queries records and vectors"| node_postgres
node_retrieval -->|"uses policy corpus"| node_wiki_seed
node_main_session -->|"configures model session"| node_providers
node_main_session -->|"emits workflow events"| node_sse_bus
node_sse_bus -->|"streams redacted events"| node_sse_api
node_sse_api -->|"live updates"| node_api_client
node_migrations -->|"evolves schema"| node_postgres
node_docker -->|"deploys"| node_fastapi
node_docker -->|"serves via nginx"| node_spa
node_docker -->|"runs"| node_postgres
node_benchmarks -.->|"evaluates"| node_fastapi

click node_spa "https://github.com/tinhnguyen0110/shb-digital/blob/master/frontend/src/Workspace.tsx"
click node_api_client "https://github.com/tinhnguyen0110/shb-digital/blob/master/frontend/src/api/client.ts"
click node_fastapi "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/main.py"
click node_auth "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/auth/router.py"
click node_conversations "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/api/conversations.py"
click node_approvals_api "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/api/approvals.py"
click node_sse_api "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/api/sse.py"
click node_main_session "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/orch/main_session.py"
click node_dispatch "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/orch/dispatch.py"
click node_specialists "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/mount/mount_role.py"
click node_retrieval "https://github.com/tinhnguyen0110/shb-digital/blob/master/roles/_retrieval/functions.py"
click node_action_gate "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/orch/gated.py"
click node_sse_bus "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/sse/bus.py"
click node_postgres "https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/db/models.py"
click node_providers "https://github.com/tinhnguyen0110/shb-digital/blob/master/configs/providers.yaml"
click node_docker "https://github.com/tinhnguyen0110/shb-digital/blob/master/docker-compose.prod.yml"
click node_benchmarks "https://github.com/tinhnguyen0110/shb-digital/blob/master/bench/run_multi.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_spa,node_api_client toneBlue
class node_fastapi,node_auth,node_conversations,node_approvals_api,node_sse_api toneAmber
class node_main_session,node_dispatch,node_specialists,node_retrieval,node_action_gate,node_sse_bus toneMint
class node_postgres,node_migrations,node_wiki_seed toneRose
class node_providers,node_docker,node_benchmarks toneIndigo
```

## Components

### Client & staff

- [React workspace](https://github.com/tinhnguyen0110/shb-digital/blob/master/frontend/src/Workspace.tsx): React SPA · Customer workspace and admin control tower. · `frontend/src/Workspace.tsx`
- [REST/SSE client](https://github.com/tinhnguyen0110/shb-digital/blob/master/frontend/src/api/client.ts): TypeScript client · `frontend/src/api/client.ts`

### API & identity

- [FastAPI application](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/main.py): Python API · Serves chat, approval, audit, metrics, and model APIs. · `backend/app/main.py`
- [Cookie JWT auth](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/auth/router.py): identity router · Enforces customer and bank/admin personas. · `backend/app/auth/router.py`
- [Conversation API](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/api/conversations.py): chat router · `backend/app/api/conversations.py`
- [Approval API](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/api/approvals.py): admin router · Staff decisions resume pending work. · `backend/app/api/approvals.py`
- [Live stream API](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/api/sse.py): SSE router · `backend/app/api/sse.py`

### Agent runtime

- [MAIN session](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/orch/main_session.py): durable orchestrator · Plans, delegates, waits, and synthesizes dynamically. · `backend/app/orch/main_session.py`
- [Role dispatch](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/orch/dispatch.py): async dispatcher · Tracks delegated tasks, retries, and resumption. · `backend/app/orch/dispatch.py`
- [Specialist roles](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/mount/mount_role.py): mounted agents · Role prompts and business tools are loaded outside the orchestrator. · `backend/app/mount/mount_role.py`
- [Policy retrieval](https://github.com/tinhnguyen0110/shb-digital/blob/master/roles/_retrieval/functions.py): shared tools · Combines wiki lineage, vector notes, and entity checks. · `roles/_retrieval/functions.py`
- [Controlled action gate](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/orch/gated.py): transactional guard · Claims approved actions and records operation receipts. · `backend/app/orch/gated.py`
- [Redacted event bus](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/sse/bus.py): SSE bus · Redacts agent traces and events before delivery. · `backend/app/sse/bus.py`

### State & knowledge

- [PostgreSQL system of record](https://github.com/tinhnguyen0110/shb-digital/blob/master/backend/app/db/models.py): PostgreSQL 15 · Stores banking state, workflow state, approvals, audit, retrieval, and cost metrics. · `backend/app/db/models.py`
- **Schema migrations**: Alembic
- **Policy wiki seed**: knowledge corpus

### Deployment & providers

- [Model providers](https://github.com/tinhnguyen0110/shb-digital/blob/master/configs/providers.yaml): provider configuration · Per-session Claude, GLM, GPT gateway, or Ollama selection stays server-side. · `configs/providers.yaml`
- [Production Compose](https://github.com/tinhnguyen0110/shb-digital/blob/master/docker-compose.prod.yml): Docker deployment · Runs PostgreSQL, backend, frontend, and deployed access services. · `docker-compose.prod.yml`
- [Benchmark runners](https://github.com/tinhnguyen0110/shb-digital/blob/master/bench/run_multi.py): evaluation CLI · `bench/run_multi.py`

## Connections

- React workspace → REST/SSE client: uses
- REST/SSE client → FastAPI application: REST and SSE
- FastAPI application → Cookie JWT auth: authenticates
- FastAPI application → Conversation API: routes chat
- FastAPI application → Approval API: routes decisions
- FastAPI application → Live stream API: routes streams
- Conversation API → MAIN session: creates or resumes
- Approval API → MAIN session: wakes on decision
- MAIN session → Role dispatch: delegates
- Role dispatch → Specialist roles: runs roles
- Specialist roles → Policy retrieval: retrieves policy and entities
- Specialist roles → Controlled action gate: requests sensitive actions
- Controlled action gate → PostgreSQL system of record: atomically updates
- MAIN session → PostgreSQL system of record: persists sessions and tasks
- Policy retrieval → PostgreSQL system of record: queries records and vectors
- Policy retrieval → Policy wiki seed: uses policy corpus
- MAIN session → Model providers: configures model session
- MAIN session → Redacted event bus: emits workflow events
- Redacted event bus → Live stream API: streams redacted events
- Live stream API → REST/SSE client: live updates
- Schema migrations → PostgreSQL system of record: evolves schema
- Production Compose → FastAPI application: deploys
- Production Compose → React workspace: serves via nginx
- Production Compose → PostgreSQL system of record: runs
- Benchmark runners → FastAPI application: evaluates
