diff --git a/docs/Flow Diagram.mmd b/docs/Flow Diagram.mmd
new file mode 100644
index 0000000..3871787
--- /dev/null
+++ b/docs/Flow Diagram.mmd
@@ -0,0 +1,44 @@
+## Flow diagram
+
+```mermaid
+flowchart TB
+ advisor(["Advisor (browser)"])
+ ui["Advisor UI
S3 + CloudFront
(split view)"]
+
+ subgraph entry["Entry / orchestration"]
+ fusion["Fusion SaaS (prod)
— or —
/demo Lambda (Fusion-less dry run)"]
+ end
+
+ subgraph cloudzone["CLOUD zone (Zone=cloud-VPC-B) — sees TOKENS only"]
+ runtime["AgentCore Runtime
Strands agent + Bedrock
apac Claude 3.5 Sonnet v2"]
+ gateway["AgentCore Gateway
MCP · AWS_IAM / SigV4"]
+ end
+
+ subgraph onprem["ON-PREM zone (Zone=on-prem-VPC-A) — holds the reversible map + PII"]
+ tokenize["/tokenize Lambda (in-VPC)
detect → mint → vault → splice"]
+ presidio["Presidio detector
Fargate (PRIVATE, SG-locked :5001)"]
+ vault[("DynamoDB VAULT
token <-> PII (+customer_id)")]
+ customers[("DynamoDB CUSTOMERS
raw records — never leave")]
+ rag["RAG tool Lambda
token -> evidence (no PII out)"]
+ restore["/restore Lambda
re-attach identity"]
+ end
+
+ advisor -- "1 query: 王小明 + A123456789" --> ui
+ ui -- "POST {query}" --> fusion
+ fusion -- "2 {query}" --> tokenize
+ tokenize -- "POST /analyze" --> presidio
+ presidio -- "typed findings" --> tokenize
+ tokenize -- "write {token,type,value,session}" --> vault
+ tokenize -- "3 deidentified_prompt (CUST_*)" --> runtime
+ runtime -- "4 tools/call get_customer_activity_summary(CUST_*)" --> gateway
+ gateway -- "5 invoke (SigV4)" --> rag
+ rag -- "6 resolve token" --> vault
+ rag -- "read record" --> customers
+ rag -- "7 evidence package (token-keyed, no PII)" --> runtime
+ runtime -- "talking points (tokens only)" --> fusion
+ fusion -- "8 {session_id, text}" --> restore
+ restore -- "lookup session tokens" --> vault
+ restore -- "final: (客戶:王小明)…" --> fusion
+ fusion -- "{final, deidentified_prompt, agent_tokenized}" --> ui
+ ui -- "split view: restored vs tokenized" --> advisor
+```
\ No newline at end of file
diff --git a/docs/Sequence Diagram.mmd b/docs/Sequence Diagram.mmd
new file mode 100644
index 0000000..df86a66
--- /dev/null
+++ b/docs/Sequence Diagram.mmd
@@ -0,0 +1,34 @@
+─```mermaid
+sequenceDiagram
+ autonumber
+ actor A as Advisor
+ participant UI as UI (S3/CloudFront)
+ participant F as Fusion
+ participant TK as tokenize (on-prem)
+ participant PR as Presidio (private)
+ participant V as Vault (DynamoDB)
+ participant RT as AgentCore Runtime + Bedrock (cloud)
+ participant GW as AgentCore Gateway (cloud)
+ participant RG as RAG Lambda (on-prem)
+ participant RS as restore (on-prem)
+
+ A->>UI: query with 王小明 + A123456789
+ UI->>F: POST {query}
+ F->>TK: {query}
+ TK->>PR: POST /analyze
+ PR-->>TK: typed findings
+ TK->>V: write token to PII map (session)
+ TK-->>F: deidentified_prompt (CUST_*)
+ F->>RT: {prompt: CUST_*}
+ Note over RT,GW: cloud sees TOKENS only
+ RT->>GW: tools/call get_customer_activity_summary(CUST_*)
+ GW->>RG: invoke (SigV4)
+ RG->>V: resolve token to customer_id
+ RG-->>RT: de-identified evidence package
+ RT-->>F: talking points (tokens only)
+ F->>RS: {session_id, text}
+ RS->>V: lookup session tokens
+ RS-->>F: final (王小明 restored)
+ F-->>UI: {final, deidentified_prompt, agent_tokenized}
+ UI-->>A: split view (restored vs tokenized)
+```
\ No newline at end of file
diff --git a/docs/architecture.md b/docs/architecture.md
index 94efe45..ae99d58 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -27,89 +27,11 @@ demo proves data-flow behaviour, not physical residency.
| 4-6 | RAG tool | `lambda_rag/` | Lambda | on-prem | ✅ resolves token, returns none |
| 8 | `/restore` | `gateway_api/restore/` | Lambda + API Gateway | on-prem | ✅ re-attaches identity |
-## Flow diagram
-```mermaid
-flowchart TB
- advisor(["Advisor (browser)"])
- ui["Advisor UI
S3 + CloudFront
(split view)"]
- subgraph entry["Entry / orchestration"]
- fusion["Fusion SaaS (prod)
— or —
/demo Lambda (Fusion-less dry run)"]
- end
+## Flow (ASCII fallback)
- subgraph cloudzone["CLOUD zone (Zone=cloud-VPC-B) — sees TOKENS only"]
- runtime["AgentCore Runtime
Strands agent + Bedrock
apac Claude 3.5 Sonnet v2"]
- gateway["AgentCore Gateway
MCP · AWS_IAM / SigV4"]
- end
- subgraph onprem["ON-PREM zone (Zone=on-prem-VPC-A) — holds the reversible map + PII"]
- tokenize["/tokenize Lambda (in-VPC)
detect → mint → vault → splice"]
- presidio["Presidio detector
Fargate (PRIVATE, SG-locked :5001)"]
- vault[("DynamoDB VAULT
token <-> PII (+customer_id)")]
- customers[("DynamoDB CUSTOMERS
raw records — never leave")]
- rag["RAG tool Lambda
token -> evidence (no PII out)"]
- restore["/restore Lambda
re-attach identity"]
- end
-
- advisor -- "1 query: 王小明 + A123456789" --> ui
- ui -- "POST {query}" --> fusion
- fusion -- "2 {query}" --> tokenize
- tokenize -- "POST /analyze" --> presidio
- presidio -- "typed findings" --> tokenize
- tokenize -- "write {token,type,value,session}" --> vault
- tokenize -- "3 deidentified_prompt (CUST_*)" --> runtime
- runtime -- "4 tools/call get_customer_activity_summary(CUST_*)" --> gateway
- gateway -- "5 invoke (SigV4)" --> rag
- rag -- "6 resolve token" --> vault
- rag -- "read record" --> customers
- rag -- "7 evidence package (token-keyed, no PII)" --> runtime
- runtime -- "talking points (tokens only)" --> fusion
- fusion -- "8 {session_id, text}" --> restore
- restore -- "lookup session tokens" --> vault
- restore -- "final: (客戶:王小明)…" --> fusion
- fusion -- "{final, deidentified_prompt, agent_tokenized}" --> ui
- ui -- "split view: restored vs tokenized" --> advisor
-```
-
-## Sequence (the 8-step round trip)
-
-```mermaid
-sequenceDiagram
- autonumber
- actor A as Advisor
- participant UI as UI (S3/CloudFront)
- participant F as Fusion or demo
- participant TK as tokenize (on-prem)
- participant PR as Presidio (private)
- participant V as Vault (DynamoDB)
- participant RT as AgentCore Runtime + Bedrock (cloud)
- participant GW as AgentCore Gateway (cloud)
- participant RG as RAG Lambda (on-prem)
- participant RS as restore (on-prem)
-
- A->>UI: query with 王小明 + A123456789
- UI->>F: POST {query}
- F->>TK: {query}
- TK->>PR: POST /analyze
- PR-->>TK: typed findings
- TK->>V: write token to PII map (session)
- TK-->>F: deidentified_prompt (CUST_*)
- F->>RT: {prompt: CUST_*}
- Note over RT,GW: cloud sees TOKENS only
- RT->>GW: tools/call get_customer_activity_summary(CUST_*)
- GW->>RG: invoke (SigV4)
- RG->>V: resolve token to customer_id
- RG-->>RT: de-identified evidence package
- RT-->>F: talking points (tokens only)
- F->>RS: {session_id, text}
- RS->>V: lookup session tokens
- RS-->>F: final (王小明 restored)
- F-->>UI: {final, deidentified_prompt, agent_tokenized}
- UI-->>A: split view (restored vs tokenized)
-```
-
-## ASCII fallback
```
┌──────────────────────────────────────────────┐
@@ -123,53 +45,53 @@ sequenceDiagram
│ S3 + CloudFront │──POST─────▶│ • Fusion SaaS (prod) │ stands in for Fusion
│ (split view) │ {query} │ • /demo Lambda (dry run) │ only, in the demo
└─────────────────┘◀───────────│ tokenize→agent→restore │
- ▲ {final, └───────────┬───────────────┘
+ ▲ {final, └────────────┬──────────────┘
│ deidentified, │
│ agent_tokenized} │ 2 {query}
════════╪════════════════════════════════════╪════════ TRUST BOUNDARY (public HTTPS + x-api-key)
ON-PREM│ (Zone=on-prem-VPC-A) ▼
- │ ┌───────────────────────┐ findings ┌────────────────────┐
- │ │ /tokenize Lambda │────────────▶│ Presidio detector │
- │ │ (in VPC) │◀────────────│ Fargate (PRIVATE, │
- │ │ detect→mint→vault→splice│ │ SG-locked :5001) │
- │ └───────┬───────────────┘ └────────────────────┘
+ │ ┌────────────────────────┐ findings ┌────────────────────┐
+ │ │/tokenize Lambda │────────────▶│ Presidio detector │
+ │ │(in VPC) │◀────────────│ Fargate (PRIVATE, │
+ │ │detect→mint→vault→splice│ │ SG-locked :5001) │
+ │ └───────┬────────────────┘ └────────────────────┘
│ │ write {token,type,value,session}
│ ▼
│ ┌───────────────────────┐ (VPC gateway endpoint)
- │ │ DynamoDB VAULT │◀────────────────┐
- │ │ token ⇄ PII (+cust_id) │ │
+ │ │ DynamoDB VAULT │◀────────────────┐
+ │ │ token ⇄ PII (+cust_id)│ │
│ └───────────────────────┘ │
- │ deidentified_prompt = "…CUST_317499…" ← TOKENS ONLY │
-════════╪═════════════════════════════════│═════════════════════════════════╪══════════════
- CLOUD │ (Zone=cloud-VPC-B) │ 3 │ resolve token
- │ ▼ │
- │ ┌────────────────────────┐ │
- │ │ AgentCore RUNTIME │ │
- │ │ Strands agent + Bedrock│ │
- │ │ (apac Claude 3.5 Sonnet)│ │
- │ └───────────┬────────────┘ │
- │ │ 4 tools/call (MCP, SigV4) │
- │ ▼ get_customer_activity_summary │
- │ ┌────────────────────────┐ │
- │ │ AgentCore GATEWAY (MCP) │ │
- │ │ AWS_IAM auth │ │
- │ └───────────┬────────────┘ │
- │ ← trace shows ONLY tokens │ 5 invoke │
-════════╪══(王小明: 0 hits, CUST_: 13)═══│═════════════════════════════════════╪══════════════
- ON-PREM│ ▼ │
- │ ┌────────────────────────┐ 6 reads │
- │ │ RAG tool Lambda │─────────────────────┘
- │ │ token→customer_id→ │ ┌────────────────────┐
- │ │ de-identified evidence │─────▶│ DynamoDB CUSTOMERS │ ← raw PII
- │ │ (raw record stays here) │ read │ (never leaves zone)│ stays put
+ │ deidentified_prompt = "…CUST_317499…" ← TOKENS ONLY │
+════════╪═════════════════════════════════│════════════════════════════════╪══════════════
+ CLOUD │ (Zone=cloud-VPC-B) │ 3 │ resolve token
+ │ ▼ │
+ │ ┌─────────────────────────┐ │
+ │ │ AgentCore RUNTIME │ │
+ │ │ Strands agent + Bedrock│ │
+ │ │ (Claude 3.5 Sonnet). │ │
+ │ └───────────┬─────────────┘ │
+ │ │ 4 tools/call (MCP, SigV4) │
+ │ ▼ get_customer_activity_summary│
+ │ ┌────────────────────────┐ │
+ │ │ AgentCore GATEWAY (MCP) │ │
+ │ │ AWS_IAM auth │ │
+ │ └───────────┬────────────┘ │
+ │ ← trace shows ONLY tokens │ 5 invoke │
+════════╪══(王小明: 0 hits, CUST_: 13)════│═════════════════════════════════╪══════════════
+ ON-PREM│ ▼ │
+ │ ┌────────────────────────┐ 6 reads │
+ │ │ RAG tool Lambda │────────────────────┘
+ │ │ token→customer_id→ │ ┌────────────────────┐
+ │ │ de-identified evidence │─────▶│ DynamoDB CUSTOMERS │ ← raw PII
+ │ │ (raw record stays here)│ read │ (never leaves zone)│ stays put
│ └───────────┬────────────┘ └────────────────────┘
│ │ 7 evidence package (token-keyed, no PII)
│ ▼ → agent writes talking points (tokens only)
│ ┌────────────────────────┐
- │ 8 {session_id, │ /restore Lambda │
- └───────────────────▶│ vault lookup by session │ prepend 王小明 + swap inline tokens
- final = "(客戶:王小明)…" │ re-attach identity │
- ← PII restored on-prem └────────────────────────┘
+ │ 8 {session_id, │ /restore Lambda │
+ └───────────────────▶│ vault lookup by session│ prepend 王小明 + swap inline tokens
+ final = "(客戶:王小明)…" │ re-attach identity │
+ ← PII restored on-prem └────────────────────────┘
```
## Auth & network per hop
@@ -190,3 +112,4 @@ Notes:
orchestrator only stands in for Fusion's orchestration in the Fusion-less dry run.
- Tokens are **random per request** (`CUST_` for a PERSON, `TW_` for a
Taiwan ROC ID); the reversible map lives only in the on-prem vault.
+
\ No newline at end of file
diff --git a/seed/customers.json b/seed/customers.json
index be8aae9..ebae203 100644
--- a/seed/customers.json
+++ b/seed/customers.json
@@ -8,5 +8,15 @@
"product_type": "funds, income-generating products",
"risk_profile": "conservative",
"sales_constraints": "avoid high-volatility products"
+ },
+ {
+ "customer_id": "cust-0002",
+ "name": "Conan Scott",
+ "national_id": "F225793148",
+ "activity_summary": "compulsive day-trading, 200+ speculative trades/week, 90 days",
+ "amount_band": "leveraged well beyond net worth (>10x margin)",
+ "product_type": "0DTE options, leveraged crypto, meme stocks, junk bonds",
+ "risk_profile": "recklessly aggressive; ignores every suitability warning",
+ "sales_constraints": "none observed; chases volatility, doubles down on losses"
}
]