The protection layer
One script, wire-protection.sh, turns the "before" demo into the "after" demo. It creates
everything below and nothing else; deleting it puts the suite back exactly as it was.
# in config.sh
export DEPLOY_PROTECTION="true" # ./deploy.sh then wires the protection layer too
export PROTECTION_MODE="block" # or "log" to detect without blocking
./wire-protection.sh # apply (safe to re-run)
./wire-protection.sh --remove # tear it back down for a clean "before" run
1. DLP profiles
Four custom profiles, shared by AI Gateway and Secure Web Gateway, written specifically against the data in these apps so the matches on stage are unambiguous:
Where Cloudflare already maintains a detection, these profiles borrow it rather than re-implementing it: US and UK national identifiers, US mailing addresses, ABA routing numbers and US phone numbers are Cloudflare's own predefined entries, referenced by name and resolved at deploy time. The custom regexes are only for what is specific to this company - UK residential addresses, the field names in these apps' JSON, and the vocabulary of its HR case files.
| Profile | Detects |
|---|---|
| Employee PII | Home address formats used in WorkWeek, national ID numbers, bank sort codes and account numbers, dates of birth. |
| HR Case Files | The vocabulary of an HR case file: performance improvement plan, grievance, disciplinary, severance, redundancy, garden leave. |
| Confidential Projects and Transactions | Project Ironwood, the acquisition target's name, the Q1 restructure and board pre-read material. |
| Customer Contact Data | Direct mobile numbers and named customer contacts from Pipeline, plus deal economics (discount and margin). |
2. AI Gateway policies
The gateway itself is not created here — wire-access.sh creates it and
publishes it on its own Access-protected custom domain, because that is identity plumbing rather
than inspection. Clients are therefore configured against the same endpoint whether or not this
layer is deployed. What this adds to it:
- DLP policies referencing all four profiles, checking both the request and the response — so it catches a user asking for an address and a model returning one it picked up from a tool result.
- Guardrails covering two different jobs.
P1 (Prompt Injection)blocks on prompts, which is what stops the poisoned wiki page from steering the agent.S1,S2,S9andS11— violent crime, non-violent crime, indiscriminate weapons, self-harm — block on both prompt and response, governing what staff can make the company's AI do at all.S7 (Privacy)is left on flag: these apps discuss people all day, so blocking it would break ordinary use, and DLP already covers the actual identifiers. - Logging on, so every one of the demos leaves an entry you can open on stage.
3. MCP server portal
The five MCP servers are registered with Cloudflare Access and published through a single portal at
:
- Users authenticate to the portal through Access, then to each upstream server as themselves
(
on_behalf), so Delta's own permissions still apply upstream. - Access policies control which servers each person even sees in the portal. Four allow the
All Employees policy;
allows only Executives, which is why Ledger's tools are absent from an ordinary employee's tool list rather than merely refused. See the access-control script. - Route traffic through Cloudflare Gateway is turned on, which is what makes the next section possible. The portal terminates the client connection and re-originates it, so Gateway can decrypt and inspect the tool traffic without any account-wide TLS decryption setting.
- Every tool call is logged in Access, independently of Gateway.
Registering an MCP server over the API cannot perform the upstream OAuth login it requires -
that needs a browser - so each server starts in Waiting with no tools. Authenticate
each one as delta.graham@company.com before running any demo — except Ledger,
which only the leadership team can authenticate, so use nikita.crist@company.com for
that one:
the setup guide has the steps, including why authenticating as the admin
account fails and what to do if a server reports that Gateway blocked its tool sync.
4. Gateway HTTP policies
One DLP policy per upstream MCP hostname. Gateway policies for portal traffic have to match the
upstream server, not the portal, so there is a rule for each of , ,
, and , each pairing that host with the
profiles that matter for it. In block mode a matching tool call or tool result is blocked and the agent gets an
error instead of the data; in log mode it is allowed and recorded.
Cloudflare's predefined AI Prompt DLP profiles are built for the API shapes of consumer AI web apps and do not match the MCP protocol, so portal traffic is inspected with the standard and custom profiles above instead. The AI Prompt profiles still have a place in this story — on Gateway HTTP policies for staff using ChatGPT or Gemini in a browser — just not on this path.
Where each control shows up
| Control | Where to look on stage |
|---|---|
| AI Gateway DLP and guardrails | AI → AI Gateway → employee-gateway → Logs. Blocked requests show the profile or hazard category that matched. |
| Gateway HTTP DLP policies | Zero Trust → Insights → Logs → Gateway HTTP. Filter by the upstream MCP hostname. |
| MCP portal | Zero Trust → Access controls → MCP Portals → the portal's logs: who called which tool, with which arguments. |
| Access | Zero Trust → Insights → Logs → Access, to show the login that produced the identity behind all of it. |
Before any of this runs, the model endpoint is already behind Access on its own custom
domain: AI Gateway accepts a valid Access JWT as the request credential, so an agent
authenticates as a person rather than with an API key, and every call is attributed to that
person as cf.user_id. A device enrolled in the Cloudflare One client authenticates
from its existing session, so there is no credential in the client's config at all.
That is what makes the logs below worth looking at: each one names a human.
What it deliberately does not do
It does not change a line of application code, and it does not fix the leaky endpoints. That is the argument: the apps are still exactly as over-sharing as they were on the data page, and the control sits in the path instead of in a backlog.