The ASCII block is the flow/topology diagram, not the sequence. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9.5 KiB
9.5 KiB
Architecture & data flow
Reversible PII de-identification round trip for HNCB. An advisor query with a real name is tokenized before it leaves for the cloud; the AgentCore agent reasons on tokens only; identity is restored on-prem before the advisor sees the answer.
Everything runs in one AWS account (ap-southeast-1); the trust zones are
logical, represented by tags (Zone=on-prem-VPC-A vs Zone=cloud-VPC-B) — the
demo proves data-flow behaviour, not physical residency.
Core invariant: cloud-zone components (AgentCore Runtime, Gateway, Bedrock) never receive the real name. Proven live — for one session the token
CUST_*appeared in 13 CloudWatch trace events while王小明/A123456789appeared in 0.
Component reference
| # | Component | Repo | AWS resource | Zone | Sees real PII? |
|---|---|---|---|---|---|
| UI | Advisor split-view UI | ui/ |
S3 + CloudFront | cloud (host) | shows restored answer to the advisor |
| entry | Orchestration | fusion/ (prod) · gateway_api/orchestrator/ (dry run) |
Fusion SaaS · /demo Lambda |
— | ✅ owns the flow |
| 2 | /tokenize |
gateway_api/tokenize/ |
Lambda (in-VPC) + API Gateway | on-prem | ✅ mints the map |
| 2 | PII detector | presidio/ |
Fargate (private, SG-locked :5001) |
on-prem | typed findings only |
| 2,4,8 | Token vault | terraform/main.tf |
DynamoDB …-vault |
on-prem | ✅ reversible map |
| 4-6 | Customer records | seed/ |
DynamoDB …-customers |
on-prem | ✅ never leave zone |
| 3,7 | Cloud agent + model | agent/ |
AgentCore Runtime + Bedrock (apac Claude 3.5 Sonnet v2) | cloud | ❌ tokens only |
| 4 | Tool bridge | scripts/agentcore_setup.sh |
AgentCore Gateway (MCP, AWS_IAM) | cloud | ❌ tokens only |
| 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 (ASCII fallback)
┌──────────────────────────────────────────────┐
Advisor │ "請問客戶 王小明 (A123456789) 最近三個月…" │ ← REAL PII
(browser) └──────────────────────────────────────────────┘
│ │
│ 1 │
▼ ▼
┌─────────────────┐ ┌───────────────────────────┐
│ Advisor UI │ │ Entry / orchestration │
│ 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, └────────────┬──────────────┘
│ 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) │
│ └───────┬────────────────┘ └────────────────────┘
│ │ write {token,type,value,session}
│ ▼
│ ┌───────────────────────┐ (VPC gateway endpoint)
│ │ 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│ │
│ │ (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 └────────────────────────┘
Auth & network per hop
| Hop | Transport | Auth |
|---|---|---|
| UI → entry | public HTTPS | /demo (dry run) or Fusion SaaS (prod) |
entry → /tokenize, /restore |
public API Gateway (HTTPS) | shared secret (x-api-key / bearer, checked in-handler) |
/tokenize → Presidio |
private (in-VPC) | Presidio SG allows only the tokenize Lambda's SG |
/tokenize,/restore,RAG → DynamoDB |
AWS API | IAM (tokenize reaches it via a VPC gateway endpoint) |
| Runtime → Gateway → RAG | MCP over HTTPS | SigV4 (AWS_IAM); runtime role has bedrock-agentcore:InvokeGateway, gateway role has lambda:InvokeFunction |
Notes:
- The UI is cloud-hosted but only ever displays the restored answer to the authorized advisor; the cloud reasoning path (Runtime/Gateway/Bedrock) is the part that never sees PII.
- Fusion is shared SaaS and is never built or hosted here. The
/demoorchestrator only stands in for Fusion's orchestration in the Fusion-less dry run. - Tokens are random per request (
CUST_<rand>for a PERSON,TW_<rand>for a Taiwan ROC ID); the reversible map lives only in the on-prem vault.