Secure AI, demonstrated.
This is a control demo, not a chatbot demo. It shows how AI can answer useful business questions while identity, policy, access, audit, and evidence stay outside the model.
Every AI deployment answers three questions, whether anyone asked them or not. What can the model read? What can users send it? And what can it touch?
Most deployments answer all three by accident. What I'll show you is a working system that answers each one deliberately, and proves it live.
Blast radius is a design decision.
Prompt injection is just text in an email, a document, or a web page, instructing your AI to do something you did not intend. The question is not whether malicious input reaches the model. It is what the model is able to do when it does.
Ungoverned
The model inherits every permission the connection has. Blast radius: the entire data plane. Audit trail: none.
Governed
Every call checked against policy, executed under scoped identity, logged. Default deny.
Here's the failure mode every headline shares. AI wired directly into enterprise systems means the model, or anything that hijacks it, inherits everything the connection can do.
The controls you're about to see shrink that blast radius at different boundaries.
APEX checks the call before AI touches data.
The model does not decide whether it is allowed. The architecture does. A capability call is checked by identity, policy, scoped access, audit, and safe response handling.
Entra ID, role, group, app identity, and session context.
Tool catalog, approved action, risk tier, and workflow boundary.
Input shape, data type, time window, routing, and exceptions.
Managed identity, least privilege, resource RBAC, and VNet boundary.
Identity, source, capability, result, decision, and policy reason.
Source-backed answer, refusal, redaction, hold, or escalation.
A prompt-injected model cannot talk its way past managed identity or RBAC. Those layers do not read English.
This is the frame for the rest of the demo. APEX is not trying to make the model safe by instruction. It makes the model operate inside boundaries it cannot talk its way around.
Now I will show three live boundaries: what the model can read, what users can send, and what AI can touch.
Security-trimmed retrieval.
Most AI data exposure does not start with an attacker. It starts with retrieval flattening your permission model. Enforcement here happens before the model, not after.
All 8 documents return, including 4 marked partner-only. This is what most RAG vendors ship.
4 documents. Partner-only content was never retrieved, so there was nothing to hide in the answer.
All 8 documents, because policy allows it, not because the filter is missing.
Filter: group_ids/any(g: search.in(g, 'demo-sg-allstaff', ',')) JUNIOR USER → Displayed results: 4 (AllStaff only) PARTNER USER → Displayed results: 8 (AllStaff + PartnerOnly) Model answer (junior): "PartnerOnly content was not included."
Production note: the filter is built by the gateway from the caller's identity token. The application never holds an admin key and cannot opt out.
Control A governs what the model can read. Watch three queries against the same index.
First, no filter. Eight documents come back, four of them partner-only. This is what a naive deployment looks like.
Now a junior user. Their group membership becomes the retrieval filter: four documents. The partner content is not redacted from the answer. It was never retrieved. The model cannot leak what it never saw.
Partner user: all eight, because they are entitled, not because the control is absent.
The DLP egress boundary.
Sensitive data can leave through helpful use, not only attack. This gateway sits between your people and every model endpoint they are allowed to use.
Passes untouched. allowed
Redacted before it leaves. The model receives the placeholder, answers, and never sees the value. redacted
Never forwarded at all. blocked
{ "user_id": "paul-demo",
"policy_hits": [ { "rule": "US_SSN", "match_preview": "12[REDACTED]89" } ],
"gateway_action": "redacted",
"forwarded_prompt": "Please process this fake SSN [REDACTED_SSN] ...",
"forwarded_to_model": true }
{ "gateway_action": "blocked", "forwarded_to_model": false }
Production note: demo rules are regex; the production swap is Purview DLP or Presidio behind the same endpoint. The shape of the record is what your auditor wants.
Control B governs what users can send. Access control does not solve the case where a valid user pastes the wrong information into the wrong tool.
Three requests through the gateway. A clean prompt passes untouched. A prompt containing a social security number is redacted before it leaves. The same prompt under a block policy never leaves at all.
Every decision, whether allowed, redacted, or blocked, writes an audit record: who, which rule, what action, and whether anything reached the model.
Deterministic retrieval. The model never writes SQL.
The market's answer to "let AI query the database" is often text-to-SQL: the model writes queries and you hope. Here, the model's only job is to say what the user meant.
Natural language in, structured JSON out. Nothing else.
Is the intent allowed? Are the parameters legal? Enum-constrained, whitelist-checked.
Under an account that can do nothing else.
1. Allowed stored procedure call... Allowed result: Region=North, TotalRevenue=400000.00 2. Forbidden direct table read, as the AI's own account... EXPECTED DENIAL: The SELECT permission was denied on the object 'Revenue', database 'db-secureai', schema 'dbo'.
Three layers of defense, and the last one is enforced by the SQL engine. No prompt injection can talk its way past a permission that does not exist.
Control C is the one that turns governance into architecture. The model never receives credentials and never generates SQL. It extracts intent and parameters only.
The app executes one whitelisted stored procedure, under a database account scoped to that procedure alone.
Then we ask the database for a direct SELECT as the AI account, and SQL Server refuses. That denial is not a prompt rule. It is enforced by the database engine.
Audit is not a report after the fact. It is part of the call.
The audit trail records allowed calls, denied calls, redactions, holds, source context, and policy reasons. In an incident, this turns an unbounded question into a bounded one.
| Time | Caller | Capability | Resource | Result | Reason |
|---|---|---|---|---|---|
| 19:14:02 | demo.user | document_lookup | Azure AI Search | ALLOW | Group entitled, source current |
| 19:15:31 | demo.user | partner_doc | Azure AI Search | DENY | Caller not in PartnerOnly group |
| 19:16:09 | demo.user | prompt_with_ssn | Model endpoint | REDACT | DLP policy matched US_SSN |
| 19:17:44 | demo.user | raw_sql | Azure SQL | DENY | Capability not approved |
| 19:18:02 | sales.agent | send_email | Outlook | HOLD | External send requires approval |
Audit is where this becomes examinable. A policy may say what should happen. APEX records what actually happened.
When security asks what AI touched, who asked, what policy applied, and whether anything left the boundary, this table is the start of the answer.
A governed system does not have to answer everything.
A useful enterprise AI system can answer when sources support it, refuse when they do not, and escalate when a human decision is required.
Source-backed answer
"Yes. The answer is supported by Customer Support Procedure Rev. 4.2 and the current approved document set."
- Returns source and revision
- Includes timestamp and identity context
- Logs capability, source, and response status
Refusal or escalation
"I cannot support that answer from approved sources. Escalate to Quality, Regulatory, or the defined owner."
- Does not invent unsupported claims
- Routes the question to a human owner
- Preserves the record of why it refused
This is a key enterprise point. A governed AI system should not be measured only by how often it answers. Sometimes the correct behavior is refusal or escalation.
That is especially important for regulated documents, customer care, quality workflows, and anything that could create external reliance.
What you just saw for one table, we generate.
Control C by hand is a consulting project. The discoverer makes it a product: point it at a data source and it builds the governed stack from the schema.
Introspects the source: tables, types, relationships, sensitivity.
Governed view, metric functions, stored procedures, least-privilege grants, typed data access layer.
Trains the language model that maps user questions to allowed intents. This is the front door to the deterministic layer.
Users ask in plain language; retrieval is deterministic; AI summarizes results it was handed.
Manufacturing enterprise · governed NL interface over live ERP Industry benchmark: 8-15 specialists · $1.5M-$4.5M Our delivery: 1 architect + 2 part-time devs · 7 weeks
Everything on the previous slide was generated, not hand-built. The discoverer introspects a data source and produces the governed view, stored procedures, permission grants, and intent mapping from the schema.
That is how a governed natural-language interface over live ERP data shipped in seven weeks with three people.
Your model list becomes policy.
Which models your data may reach should be a policy decision, not a developer preference. This is especially important when teams use more than one provider.
Request passes; provider key injected server-side; tokens metered per team. 200
Refused before the request leaves your tenant, and logged. 403 · model not in policy
POST /models/chat/completions model="anthropic/claude-sonnet" 200 OK tokens metered · key never left the vault POST /models/chat/completions model="unlisted/decentralized-net" 403 Model not in policy · decision written to audit
This is a model-plane extension. It is separate from the Control A, B, and C test run.
One more surface, if your teams use more than one model: the model plane itself. Every request to every provider transits the same gateway.
An approved model passes, with the provider key injected at the gateway so no application ever holds it. Anything off policy is refused before it leaves the tenant, and the refusal is logged.
Governance lets the business say yes safely.
Control A
Control B
Control C
The demonstrated controls run on Azure AI Search, Azure OpenAI, Azure SQL, and Key Vault. The production gateway adds API Management and Entra ID at the trust boundary.
Goal: approved AI capabilities Boundary: identity · policy · scoped access · audit Evidence: every decision written down Credentials: not reachable by the model
Everything you saw is running software, on services enterprise teams already know how to operate. Nothing here requires trusting the model to behave. Every control holds even when the model does not.
The next step is a fixed-scope assessment: inventory AI assets, map what they can reach, define guardrails, and produce the remediation and pilot roadmap.
Paul Hasselbring · Founder & Principal Architect · NPM Technologies · Fort Lauderdale, FL · paulh@npmit.com