# Fusion (shared SaaS) policy setup — de-identification as a gateway policy Fusion (Axway Amplify AI Gateway) is a **shared SaaS instance**, configured in the console — not deployed by this repo. Here it is the **enforcement plane** in front of the AgentCore agent: de-identification is a **policy on the route**, not application code. `/tokenize` and `/restore` are the policy's **transform backend** (they hold the detector + vault on-prem); Fusion applies them inline to traffic. > **Why put Fusion in the path at all?** Functionally, everything below is an HTTP > call — the `/demo` orchestrator proves a plain client can do the same mechanics. > That is the point: the mechanics are **not** the differentiator. Fusion adds what > a plain call cannot: > - **Non-bypassable enforcement** — de-id is applied at the gateway to *all* AI > traffic, not trusted to each app to call `/tokenize` correctly. > - **Central audit** — the gateway's own trace is the compliance artifact proving > only tokens ever reached the model. (See the money-shot check in the README.) > - **Reuse** — one policy governs every model/agent/app behind Fusion; routing, > rate-limits, and guardrails come with it. > > Drop Fusion and you lose *enforcement and audit*, not capability. ## The policy model Fusion fronts the AgentCore Runtime as a governed route. Two policies wrap it: ``` advisor ─▶ [ Fusion route to the agent ] │ request policy (ingress) ── tokenize transform ─▶ /tokenize ▼ AgentCore Runtime (sees TOKENS only) │ response policy (egress) ── restore transform ──▶ /restore ▼ advisor ◀────┘ ``` The transforms run **inside the policy boundary**; the raw name never crosses it. ## Backend the policy calls Use the **custom domain** — Fusion could not resolve the default `*.execute-api.ap-southeast-1.amazonaws.com` endpoint, so the API is fronted by a Route53-aliased name that resolves straight to IPs (see `terraform/custom_domain.tf`). - `TOKENIZE_URL` = `https://hncb-deid.apim-apac-demo.com/tokenize` — `terraform -chdir=terraform output -raw tokenize_url_custom` - `RESTORE_URL` = `https://hncb-deid.apim-apac-demo.com/restore` — `terraform -chdir=terraform output -raw restore_url_custom` - `AGENT_RUNTIME_ARN` (the route's upstream) = printed by `scripts/agentcore_setup.sh` - **Auth:** public API Gateway HTTP API; send the shared secret in the **`x-api-key`** header (`Authorization: Bearer ` also works). The secret is the Terraform `tokenize_api_key` var (gitignored `terraform/local.auto.tfvars`, never committed) — hand it to the console operator out of band. - *Note:* the raw `…execute-api…` URLs (`output -raw tokenize_url` / `restore_url`) still work for anything that can resolve them; Fusion should use the custom domain. - *Note:* a Lambda Function URL was the first choice, but this account's SCP blocks unauthenticated Function URLs, so the public front door is API Gateway. ## Request policy — ingress (prompt bound for the agent) Applied to every request on the route; the app cannot skip it. 1. **AuthN / RBAC / business-purpose** check (Fusion native). 2. **Tokenize transform:** `POST { query }` → `TOKENIZE_URL` → `{ deidentified_prompt, session_id }`. The endpoint runs detect → mint → vault-write → splice (typed findings, never a redacted blob). **Replace** the outbound prompt with `deidentified_prompt`; carry `session_id` as policy/session context. 3. **Forward** to the AgentCore upstream with `{ "prompt": deidentified_prompt }` — tokens only. 4. **Audit:** record the **tokenized** payload; the raw query never leaves the policy. ## Response policy — egress (agent's answer) Applied to every response on the route. 1. **Restore transform:** `POST { session_id, text }` → `RESTORE_URL` → `{ final }` (vault lookup scoped to this session; re-attaches identity at the envelope and swaps any inline tokens). 2. **Return** `{ "final": ..., "deidentified_prompt": ... }` so the UI renders the restored-vs-tokenized split view. ## Vault item shape (DynamoDB, written by the tokenize transform) One row per detected entity. `value` is the original PII (so restore can put it back); a resolvable PERSON also gets a `customer_id` so the RAG tool can turn the token into a de-identified evidence package. ``` { "token": "CUST_863651", "type": "PERSON", "value": "王小明", "session_id": "", "expires_at": , "customer_id": "cust-0001" } { "token": "TW_683250", "type": "TW_ROC_ID", "value": "A123456789", "session_id": "", "expires_at": } ``` (The seed's `--with-demo-token` writes a different `type=CUSTOMER, value=cust-0001` row; that's only a standalone RAG test aid, not what the tokenize transform mints.) ## Fusion vs. the `/demo` orchestrator (be honest on camera) `gateway_api/orchestrator/` (`/demo`) runs the *identical* tokenize → agent → restore mechanics over plain HTTP, so the Fusion-less demo works end to end. Show that to prove the data-flow. Then make the governance point: only Fusion turns those mechanics into a **mandatory, audited policy** across all AI traffic — the enforcement boundary an app-level HTTP call can't guarantee. > Not automated here: Fusion is shared SaaS and configured by a human in the > console. This file is the spec for that configuration.