Content shield proxy — PII/PHI/financial/secrets detection, dictionary masking, tenant isolation, and LLM provider routing with circuit breaker.
| Feature | MaskChain | PasteGuard | CloakPipe | Bifrost | GoModel | privacy-filter |
|---|---|---|---|---|---|---|
| Language | Go (native) | TypeScript (Bun) | Rust | Go | Go | Go |
| LLM Proxy | ✅ Full proxy | ✅ Proxy | ❌ Mask-only | ✅ Full proxy | ✅ Proxy | ❌ Redact-only |
| Content Shield | ✅ PII/PHI/finance/secrets/dictionary | ✅ PII+secrets (Presidio) | ✅ PII+secrets (ONNX NER) | ✅ Prompt injection + PII | ❌ | ✅ PII+secrets only |
| Streaming Unmask | ✅ SSE response restore | ✅ SSE (partial buffer) | ✅ SSE rehydration | ❌ | ❌ | ❌ |
| Tenant Isolation | ✅ Per-tenant API keys + config | ❌ | ❌ | ❌ | ❌ | ❌ |
| Dictionary Masking | ✅ Per-tenant, 4 match modes (exact/contains/regex/fuzzy) | ❌ NER-only | ❌ NER-only | ❌ | ❌ | ❌ |
| Routing | ✅ Per-tenant per-model + fallback + CB | ❌ Single provider | ❌ | ✅ Multi-provider | ✅ Multi-provider | ❌ |
| Circuit Breaker | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Rate Limiting | ✅ Sliding window (Valkey) | ❌ | ❌ | ✅ | ❌ | ❌ |
| Cost Tracking | ✅ Token + cost analytics | ❌ | ❌ | ✅ | ❌ | ❌ |
| Admin UI | ✅ React SPA | ✅ Dashboard (SQLite) | ❌ | ❌ | ❌ | ❌ |
| Helm Chart | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| OTel Tracing | ✅ gRPC exporter | ❌ | ❌ | ❌ | ❌ | ❌ |
| Binary Size | ~18 MB (gateway) | ~200 MB+ (Bun+Presidio) | ~15 MB | ~18 MB | ~20 MB | ~15 MB |
| Startup Time | <100ms | ~2-5s | <50ms | <100ms | <100ms | <50ms |
| License | Apache 2.0 | Apache 2.0 | MIT | Open source | MIT | MIT |
MaskChain is the only Go-native LLM gateway with per-tenant dictionary masking — PII/PHI/financial/secrets regex detection plus Aho-Corasick dictionary matching (exact/contains/regex/fuzzy) and streaming SSE unmask. Unlike NER-only tools (PasteGuard, CloakPipe), it masks internal business terms — product codenames, patient IDs, trading signals — with deterministic, reversible placeholders. Unlike Python-based solutions (LiteLLM), it starts in under 100ms with a ~18 MB static binary. Unlike PII-only tools (privacy-filter, Bifrost), it's a complete proxy with routing, circuit breaker, rate limiting, tenant isolation, and an admin UI.
- Healthcare (HIPAA): Strip PHI (patient names, SSNs, medical record numbers) from prompts before they reach OpenAI/Anthropic. Dictionary masking handles internal patient IDs.
- Fintech (PCI DSS): Detect and block credit card numbers, bank accounts, and financial secrets. Per-tenant dictionaries cover internal product codenames and trading signals.
- Legal: Redact confidential client information, case numbers, and attorney-client privileged content before sending to external LLMs.
- Internal LLM Gateway: Multi-team deployments with tenant isolation — each team gets its own API keys, rate limits, provider routing, and PII configuration.
- SaaS LLM Proxy: Offer LLM access to customers with per-tenant content policies, usage tracking, and cost allocation.
┌─────────────────────────────────┐
Client ───► Auth ──► RateLimit ──► Shield Scan ──► Routing ──► Provider
│ │ (OpenAI/
│ ┌──────────────┐ │ Anthropic)
│ │ PostgreSQL │ │
│ │ (tenants, │ │
│ │ incidents, │ │
│ │ profiles, │ │
│ │ masks) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ Valkey │ │
│ │ (rate lim, │ │
│ │ mask cache)│ │
│ └──────────────┘ │
│ │
└────────── Fallback + CB ──────────┘
Request flow: Client sends chat completion request -> Auth middleware extracts tenant by API key -> Rate limiter checks sliding window (Valkey) -> Shield scanner runs PII regex + dictionary matching per tenant -> Router selects provider (OpenAI/Anthropic) with circuit breaker health check -> Response is scanned and unmasked before returning.
- Gateway — proxy for LLM chat completions with content scanning
- Admin — management API + SPA (React/Vite) for tenant/dictionary/incident management
- Combined — single binary running both gateway and admin on separate ports
- PostgreSQL — tenants, incidents, profiles, mask storage
- Valkey — rate limiting (sliding window), mask cache
# Start full stack (gateway + admin + postgres + valkey + monitoring)
docker compose -f deployments/docker-compose/docker-compose.yml up -d --build
# Or use examples/ for local dev with pre-seeded data
docker compose -f examples/docker-compose.yml up -d --buildSee examples/README.md for tenant setup and test flows.
Pre-built images are available on Docker Hub:
| Image | Description |
|---|---|
bzdvdn/maskchain |
Combined gateway + admin (2-in-1) |
bzdvdn/maskchain-gateway |
Gateway only (LLM proxy + shield) |
bzdvdn/maskchain-admin |
Admin only (management API + UI) |
Images are tagged with latest (main branch), commit SHA, and SemVer tags on release.
| Service | Port | Image | Description |
|---|---|---|---|
| Gateway | 8080 | bzdvdn/maskchain-gateway |
LLM proxy + shield scan |
| Admin | 8081 | bzdvdn/maskchain-admin |
Management API + UI |
| Combined | 8080/8081 | bzdvdn/maskchain |
Both services in one binary |
| PostgreSQL | 5432 | postgres:16-alpine |
Primary store |
| Valkey | 6379 | valkey/valkey:8-alpine |
Rate limit + cache |
| Prometheus | 9090 | prom/prometheus |
Metrics (examples stack) |
| Grafana | 3000 | grafana/grafana |
Dashboards (examples stack) |
- PII/PHI/financial/secrets regex detection
- Dictionary-based entity matching per tenant
- Placeholder masking with restore via admin API
- Streaming response unmask (SSE)
- Per-tenant per-model provider routing
- Automatic fallback + circuit breaker
- Provider health checking
- Per-provider egress proxy (HTTP/HTTPS/SOCKS5) with
proxy_urlconfig - Supported
api_type:openai,anthropic,gemini,bedrock(AWS Bedrock),proxy(OpenAI-compatible),ollama
- OpenTelemetry tracing (gRPC exporter)
- Prometheus metrics (request rate, latency, shield stats, pool stats)
- Structured logging (slog) with trace IDs via OTel enrichment
MaskChain provides defense-in-depth for LLM traffic:
- PII/PHI scanning — regex-based detection of emails, phones, SSNs, credit cards, API keys, and other secrets before they reach the LLM provider
- Dictionary masking — per-tenant exact-match dictionaries (employee names, project codenames, internal identifiers) are replaced with placeholders
- Streaming unmask — masked content is restored in real-time on the response path so the client sees original values
- Tenant isolation — API key authentication per tenant with isolated PII configs and dictionaries
- Rate limiting — sliding window rate limiter per tenant (Valkey-backed)
- Secrets audit —
make security-checkruns gitleaks + config validation
See SECURITY.md for reporting vulnerabilities.
Three-layer config: YAML -> ENV (CONFIG_*) -> CLI flags.
Minimal config.yaml:
server:
port: 8080
routing:
providers:
- name: openai
api_type: openai
base_url: https://api.openai.com
api_keys: ["sk-..."]
- name: gemini
api_type: gemini
api_keys: ["${GEMINI_API_KEY}"]
- name: groq
api_type: proxy # generic OpenAI-compatible
base_url: https://api.groq.com/openai/v1
api_keys: ["${GROQ_API_KEY}"]
- name: bedrock
api_type: bedrock
aws_region: "us-east-1" # required; credentials via env/IAM
timeout: 120s
- name: anthropic-via-corp
api_type: anthropic
api_keys: ["sk-ant-..."]
proxy_url: http://corp-proxy:3128 # per-provider egress proxy
tenants:
default:
auth_header: "Authorization"
api_keys: ["sk-test-default"]See examples/config.yaml for full reference.
src/
├── cmd/
│ ├── gateway/ # Gateway entrypoint (-tags gateway)
│ ├── admin/ # Admin API + UI entrypoint (-tags admin)
│ ├── all/ # Combined entrypoint (gateway + admin)
│ └── internal/bootstrap/ # Shared init (DB, Valkey, logger)
├── internal/
│ ├── adapters/ # External integrations (providers, repos, egress)
│ ├── api/ # HTTP layer (handlers, middleware, DTOs)
│ ├── app/usecase/ # Application use cases (shield scan)
│ ├── domain/ # Domain logic (shield, routing, tenant, budget)
│ ├── infra/ # Infrastructure (config, telemetry, metrics)
│ └── ports/ # Interface definitions
└── pkg/ # Public packages
| Aho-Corasick 1000-term matching (<1ms) | Real mask/unmask round-trip (Docker) |
|---|---|
![]() |
![]() |
# Performance benchmark (Aho-Corasick, 1000 terms, no Docker needed)
bash demo/run-benchmark.sh
# Full stack demo: Docker Compose + seed + mask/unmask
bash demo/run-mask-unmask-live.shThe CI pipeline (GitHub Actions) runs on every push/PR to main:
| Stage | What it does |
|---|---|
| Lint | go mod tidy, go mod verify, golangci-lint, go vet |
| Test | go test -race -count=1 ./... with coverage artifact |
| Build | Cross-compiles gateway, admin, and combined binaries |
| Docker | Builds all three Docker images (distroless multi-stage) |
| Helm | Lints the Helm chart |
| Smoke | Starts compose stack and runs API consistency tests |
See .github/workflows/ci.yml for full workflow definition.
make build # Build both binaries
make test # Run all tests with race detector
make lint # Run golangci-lint
make security-check # gitleaks + config auditBuild tags: gateway / admin / (none for combined) — split by binary capabilities.
See CONTRIBUTING.md for detailed contribution guide.
OpenAPI 3.1 spec: src/internal/api/swagger/openapi.yaml
Swagger UI: embedded in admin binary at /swagger/.
Releases follow SemVer via git tags (v1.2.3). Version metadata is injected at build time:
-ldflags="-s -w -X github.com/bzdvdn/maskchain/src/pkg/version.Version=$(VERSION)
-X github.com/bzdvdn/maskchain/src/pkg/version.Commit=$(COMMIT)
-X github.com/bzdvdn/maskchain/src/pkg/version.Date=$(DATE)"
Binary endpoints expose version info via GET /api/v1/version.
- Examples — tenant setup, test flows, config reference
- Tutorial — 5-minute walkthrough
- Deployment Guide — Docker Compose + Helm + bare binary
- Shield Architecture — deep-dive into content shield
- Performance — benchmarks and tuning
- Runbook — production operations, debugging, recovery
- Helm Chart — Kubernetes deployment
- Roadmap — planned features and milestones
See LICENSE file.

