Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions kits/pii-sovereign-guardrail/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
.next/
.env
.env.local
*.log
.vs/
89 changes: 89 additions & 0 deletions kits/pii-sovereign-guardrail/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# PII Sovereign Guardrail

Enterprise middleware that masks personally identifiable information (PII)
before it reaches an external LLM provider (OpenAI, Anthropic, etc.), and
rehydrates it in the response — so raw personal data never leaves your
infrastructure in identifiable form.

## The problem

Enterprise legal and security teams routinely block GenAI rollouts because
raw user input — names, emails, phone numbers, addresses — ends up in a
third-party model vendor's logs. That's a real compliance blocker, not a
hypothetical one, for regulated industries like banking, healthcare-adjacent
SaaS, and legal tech.

## How it works

Two detection layers, because neither alone is honest coverage:

1. **Layer 1 — deterministic (regex).** Catches structurally predictable
PII: emails, API keys/secrets, phone numbers, credit card numbers. Fast,
free, and reliable for well-formed matches.
2. **Layer 2 — probabilistic (LLM-based NER).** Catches unstructured PII
regex can't: names, addresses, free-text personal references. Each
detection is tagged with a confidence level.

Both layers' detections are masked with indexed placeholders
(`[REDACTED_EMAIL_0]`, `[REDACTED_NAME_1]`, ...) before the prompt is sent
to the target model. After the model responds, the placeholders are swapped
back to their real values — a process that happens entirely within this
flow, never externally.

See [`agent.md`](./agent.md) for the full architecture and an honest list
of what this does and does not cover, and
[`constitutions/default.md`](./constitutions/default.md) for the hard
guardrails the flow must never violate (e.g. fail closed, never persist
the token map).

## Demo ![PII Guardrail demo](./docs/demo.png) *Left: what leaves your infrastructure (masked). Right: what the caller actually receives (rehydrated).*

## Structure

```
pii-sovereign-guardrail/
- lamatic.config.ts (kit metadata)
- agent.md (capability doc, read this first)
- constitutions/default.md (hard guardrails)
- flows/pii-sovereign-guardrail.ts (flow graph, real Lamatic Studio export)
- scripts/ (masking/rehydration logic, real, working
- prompts/ (Layer 2 NER prompts)
- model-configs/ (LLM configs per node)
- apps/ (Next.js demo, live masking visualization)

```

This flow is built, deployed, and tested end-to-end in Lamatic Studio.
Everything in `flows/`, `scripts/`, `prompts/`, `model-configs/`, and
`constitutions/` is the real Studio export, not a scaffold — Layer 1
(regex), Layer 2 (LLM NER), the target model call, and rehydration have
all been verified working together on live test runs.

## Running the demo locally

```bash
cd kits/pii-sovereign-guardrail/apps
cp .env.example .env.local # fill in your own Lamatic + model credentials
npm install
npm run dev
```

The app works out of the box in **demo mode** (Layer 1 only, no LLM call,
no API keys needed) so you can see the redaction pipeline immediately.
Once `.env.local` is filled in with a deployed flow's `LAMATIC_API_KEY`,
`LAMATIC_PROJECT_ID`, `LAMATIC_API_URL`, and `PII_GUARDRAIL_FLOW_ID`, it
automatically switches to the full two-layer pipeline against the real
deployed flow.

## What this does NOT do

- It is not a certified DLP system — for HIPAA/PCI-scope data, pair it with
dedicated compliance tooling.
- Layer 2 is probabilistic. It significantly improves coverage over regex
alone but is not a guarantee of catching every unstructured PII mention.
- It does not provide audit logging by itself — pair it with your existing
observability stack (e.g. Langfuse, which Lamatic already integrates with).

## Tags

`security` `compliance` `pii` `data-sovereignty` `middleware` `enterprise`
32 changes: 32 additions & 0 deletions kits/pii-sovereign-guardrail/agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# PII Sovereign Guardrail — Agent Identity

## What this agent does

The PII Sovereign Guardrail sits between your application and any external LLM
provider (OpenAI, Anthropic, etc.). It intercepts outbound prompts, masks
personally identifiable information (PII) before the prompt ever leaves your
infrastructure, sends the sanitized prompt to the target model, and then
rehydrates the original values back into the response before it's returned
to the caller.

The goal isn't "detect 100% of PII" — no system honestly can, and any kit
that claims otherwise is overselling. The goal is to give engineering and
compliance teams a **documented, auditable boundary**: a clear answer to
"what does this catch, and what doesn't it catch" so they can make an
informed decision about what still needs a human review step.

## Capabilities

1. **Deterministic masking (Layer 1)** — pattern-based detection for
structurally predictable PII: email addresses, API keys / secret tokens,
phone numbers, credit card numbers. This layer is fast, free, and has
effectively zero false negatives for well-formed instances of these
patterns.
2. **Probabilistic masking (Layer 2)** — an LLM-based named-entity
recognition pass that catches unstructured PII regex structurally cannot:
personal names, physical addresses, and free-text personal references
("my account under John Smith", "reach me at..."). Each detection carries
a confidence label.
3. **Token re-hydration** — a per-request token map (never persisted,
never sent externally) restores the original values into the model's
response before it reaches the caller.
7 changes: 7 additions & 0 deletions kits/pii-sovereign-guardrail/apps/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Get these from Lamatic Studio → Settings → API Keys (see repo CONTRIBUTING.md)
LAMATIC_API_KEY=
LAMATIC_PROJECT_ID=
LAMATIC_API_URL=

# Flow ID for the deployed pii-guardrail flow (Studio → Flow → Details panel)
PII_GUARDRAIL_FLOW_ID=
49 changes: 49 additions & 0 deletions kits/pii-sovereign-guardrail/apps/actions/orchestrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use server";
import { guardrailFlowId, createLamaticClient } from "../lib/lamatic-client";

export interface GuardrailResult {
secureResponse: string;
maskedPromptSent: string;
tokensRedacted: {
total: number;
deterministic: number;
probabilistic: number;
};
// Populated only in local demo mode (no deployed flow ID yet), so
// reviewers can see the redaction pipeline working before wiring up
// a real Lamatic Studio deployment.
demoMode?: boolean;
}

export async function runGuardrail(
rawUserPrompt: string,
targetModel: string
): Promise<GuardrailResult> {
if (!guardrailFlowId) {
// No deployed flow yet — fall back to a local demo so the app is
// still usable out of the box. Swap this out once PII_GUARDRAIL_FLOW_ID
// is set in .env.local.
const { runLocalDemoGuardrail } = await import("../lib/local-demo");
return { ...runLocalDemoGuardrail(rawUserPrompt), demoMode: true };
}

const lamatic = createLamaticClient();
const response = await lamatic.executeFlow(guardrailFlowId, {
rawUserPrompt,
targetModel
});

const result = response.result;
if (!result) {
// Fail closed — if the flow didn't return a result, don't guess
// at partial data. Surface a clear error instead.
throw new Error("Lamatic flow returned no result — masking pipeline failed.");
}

return {
secureResponse: result.secureResponse,
maskedPromptSent: result.maskedPromptSent,
tokensRedacted: result.tokensRedacted,
demoMode: false
};
}
45 changes: 45 additions & 0 deletions kits/pii-sovereign-guardrail/apps/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
:root {
--bg: #0c0f12;
--panel: #14181d;
--panel-raised: #191e24;
--border: #262b31;
--text: #e9ecef;
--text-dim: #8b939c;
--accent: #34d8a6;
--accent-dim: #1f7a5c;
--redact: #eb6a4e;
--redact-bar: #05070a;
--font-ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
--font-mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas,
monospace;
}

* {
box-sizing: border-box;
}

html,
body {
padding: 0;
margin: 0;
background: var(--bg);
color: var(--text);
font-family: var(--font-ui);
}

body {
min-height: 100vh;
}

::selection {
background: var(--accent-dim);
color: white;
}

button {
font-family: inherit;
}

a {
color: var(--accent);
}
19 changes: 19 additions & 0 deletions kits/pii-sovereign-guardrail/apps/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import "./globals.css";

export const metadata = {
title: "PII Sovereign Guardrail — Lamatic AgentKit",
description:
"Enterprise middleware that masks PII before it reaches an external LLM, and rehydrates it in the response."
};

export default function RootLayout({
children
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Loading