Files
hncb-fusion-deid-demo/docs/architecture.md
Conan Scott 4c540c6a83 docs: relabel ASCII diagram heading (Sequence -> Flow)
The ASCII block is the flow/topology diagram, not the sequence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 18:00:02 +10:00

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 王小明 / A123456789 appeared 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 /demo orchestrator 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.