VaultKit is the policy layer between your production databases and anyone or anything that queries them — AI agents, engineers, and automated systems. Field-level masking, approval workflows, signed grants, and audit trails — without exposing raw credentials.
In 2026, an AI agent at PocketOS deleted an entire production database in nine seconds — backups included. The pattern is the same across incidents: agents and automated systems with raw database credentials and no policy enforcement layer. VaultKit fixes that.
VaultKit provides enterprise-grade governance and security for data access, enabling AI agents, engineers, and automated systems to query multiple data sources through a unified, policy-controlled interface.
VaultKit is a control plane that governs how data is accessed across your organization. It centralizes authentication, authorization, policy evaluation, and access control — ensuring that every data request is properly authenticated, authorized, and audited before execution.
FUNL (Functional Universal Query Language) is the data plane and execution engine that powers VaultKit’s query capabilities. While VaultKit decides if and how data can be accessed, FUNL handles the actual execution.
FUNL is designed to be lightweight, stateless, and horizontally scalable — making it ideal for high-throughput data access scenarios.
VaultKit is built with zero-trust governance and tamper-proof enforcement at its core:
These characteristics go beyond traditional RBAC/ABAC systems and enable compliance-grade data access control.
VaultKit issues short-lived, cryptographically signed access tokens (JWT) that embed:
Tokens are verified at both the control plane (VaultKit) and execution plane (FUNL), ensuring:
This enables credential-less execution — users and AI agents never handle database passwords, only time-bound, cryptographically-signed authorization tokens.

deny > require_approval > mask > allowVaultKit’s approach to schema evolution is designed for security, auditability, and safe change management.
VaultKit deliberately separates:
This separation prevents silent data exposure. When new tables or sensitive columns appear, they require explicit policy review before access is granted.

Key Safety Principle:
Scans inform. Bundles enforce. Humans decide.
Scans never automatically update active policies. This ensures:
# 1. Discover schema changes (safe, read-only)
vkit scan production_db
# Output shows drift:
# + dataset: customers
# + field: ssn (string) [PII] NEW - requires policy
# ~ field: email (text -> varchar) [PII] Already masked
# 2. Review and update baseline
vkit scan production_db --apply
# 3. Update policies in Git
vim policies/customer_data.yaml
# 4. Build and deploy new bundle
vkit policy bundle
vkit policy deploy
name: Schema Drift Check
on: [schedule, push]
jobs:
drift-detection:
runs-on: ubuntu-latest
steps:
- name: Scan all datasources
run: vkit scan --all --fail-on-drift
- name: Create PR if drift detected
if: failure()
run: |
vkit scan --all --diff > drift-report.md
gh pr create --title "Schema Drift Detected" --body-file drift-report.md
AQL (Access Query Language) is a structured JSON format that describes what to fetch, not how. This abstraction allows VaultKit to enforce policies consistently across different database engines.
{
"source_table": "table_name",
"columns": ["field1", "field2"],
"joins": [],
"aggregates": [],
"filters": [],
"group_by": [],
"having": [],
"order_by": null,
"limit": 0,
"offset": 0
}
Simple Query:
{
"source_table": "customers",
"columns": ["email", "country", "revenue"],
"filters": [
{ "field": "country", "operator": "eq", "value": "US" },
{ "field": "revenue", "operator": "gt", "value": 10000 }
],
"limit": 100
}
FUNL Translation — PostgreSQL:
SELECT email, country, revenue
FROM customers
WHERE country = $1 AND revenue > $2
LIMIT 100
FUNL Translation — MySQL:
SELECT `email`, `country`, `revenue`
FROM `customers`
WHERE `country` = ? AND `revenue` > ?
LIMIT 100
FUNL’s Masking Dialect System applies transformations directly in SQL based on VaultKit’s policy decisions:
| Masking Type | PostgreSQL | MySQL | Snowflake |
|---|---|---|---|
| Full | '*****' AS email |
'*****' AS email |
'*****' AS email |
| Partial | CONCAT(LEFT(email, 3), '****') |
CONCAT(LEFT(email, 3), '****') |
CONCAT(LEFT(email, 3), '****') |
| Hash | ENCODE(SHA256(email::bytea), 'hex') |
SHA2(email, 256) |
SHA2(email, 256) |
| Feature | Description |
|---|---|
| AQL Orchestration | Vendor-neutral query language prevents SQL injection and enables policy enforcement |
| Policy Engine | Attribute-based access control with support for clearance levels, regions, sensitivity tags, and time windows |
| Policy Priority System | Hierarchical decision making: deny > require_approval > mask > allow |
| Field-Level Policies | Match rules based on dataset name, field sensitivity, categories (pii, financial, etc.), or specific field names |
| Context-Aware Rules | Policies evaluate requester role, clearance level, region, environment, and time constraints |
| Approval Workflows | Require manager/security approval for accessing PII, financial data, or production environments |
| Zero-Trust Sessions | Short-lived, cryptographically-signed tokens with automatic expiration |
| Credential Abstraction | Never expose database credentials to users — supports multiple secret backends |
| Git-Backed Governance | All policies and registries versioned in Git with full audit trail |
| Schema Drift Detection | Automated discovery of database changes with manual approval workflow |
| Comprehensive Auditing | Every query logged with user identity, timestamp, policy decisions, and results metadata |
| CLI & SDK | Rich command-line tools (vkit) and Python SDK for integration |
| Feature | Description |
|---|---|
| Multi-Engine Translation | Supports PostgreSQL, MySQL, Snowflake, BigQuery with identical AQL interface |
| SQL-Level Masking | Masking applied during query execution — no post-processing overhead |
| Injection Prevention | All queries use parameterized execution with proper type binding |
| Horizontal Scaling | Stateless design enables running multiple FUNL instances behind a load balancer |
| JWT Verification | Only executes queries signed by VaultKit’s private key |
Before installing VaultKit, ensure you have:
ruby --version)go version)The fastest way to get VaultKit running locally using Docker Compose:
git clone git@github.com:vaultkit-inc/vaultkit.git
cd vaultkit
cp .env.example infra/secrets/.env
Edit infra/secrets/.env:
POSTGRES_USER=vaultkit
POSTGRES_PASSWORD=secret
POSTGRES_DB=vaultkit_development
DATABASE_URL=postgres://vaultkit:secret@postgres:5432/vaultkit_development
FUNL_URL=http://funl-runtime:8080
RAILS_ENV=development
openssl genpkey -algorithm RSA -out infra/secrets/vkit_priv.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in infra/secrets/vkit_priv.pem -out infra/secrets/vkit_pub.pem
cd infra
docker compose up --build
Services:
VaultKit is now running locally. You can now configure datasources and begin querying data through the control plane.
openssl genpkey -algorithm RSA -out vaultkit_private.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in vaultkit_private.pem -out vaultkit_public.pem
export VKIT_PRIVATE_KEY="$(pwd)/vaultkit_private.pem"
export VKIT_PUBLIC_KEY="$(pwd)/vaultkit_public.pem"
export FUNL_PUBLIC_KEY="$(pwd)/vaultkit_public.pem"
Security Note: Keep your private key secure. Add
*.pemto your.gitignore.
git clone https://github.com/vaultkit-inc/vaultkitcli.git
cd vaultkitcli
gem build vaultkitcli.gemspec
gem install ./vaultkitcli-0.1.0.gem
vkit --version
pip install vaultkit
vkit login
vkit datasource add \
--id demo_db \
--engine postgres \
--username readonly_user \
--password $DB_PASSWORD \
--config '{
"host": "localhost",
"port": 5432,
"database": "analytics"
}'
vkit scan demo_db --apply
vkit request --datasource demo_db --aql '{
"source_table": "users",
"columns": ["id", "email", "created_at"],
"limit": 10
}'
vkit fetch --grant grant_abc123xyz
You are now querying data through VaultKit.
AI agents querying production databases inherit whatever permissions the underlying credential holds — and they will use all of it without hesitation. VaultKit replaces raw credentials with scoped, time-bound grants that enforce exactly what the agent is allowed to see.
The problem:
VaultKit solution:
# policies/ai_agent_restrictions.yaml
id: ai_agent_restrictions
match:
fields:
category: pii
context:
requester_role: ai_agent
environment: production
action:
mask: true
mask_type: hash
reason: "PII must be hashed for AI agents"
ttl: "15m"
How it works:
CLI Usage:
vkit request \
--datasource production_db \
--role ai_agent \
--aql '{
"source_table": "customer_behavior",
"columns": ["user_id", "email", "purchase_amount"],
"filters": [{"field": "purchase_amount", "operator": "gt", "value": 1000}]
}'
# Result: email field is hashed
# {
# "user_id": 12345,
# "email": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
# "purchase_amount": 1250.00
# }
Engineers and automated systems should never hold standing access to production data. VaultKit replaces standing privileges with time-bound, approval-gated grants that expire automatically and leave a verifiable audit trail.
The problem:
VaultKit solution:
# policies/financial_requires_approval.yaml
id: financial_break_glass
match:
fields:
category: financial
context:
environment: production
requester_role: engineer
action:
require_approval: true
approver_role: finance_manager
approval_metadata_required:
- incident_ticket
- business_justification
ttl: "1h"
reason: "Financial data access requires approval"
auto_revoke: true
Approval Workflow:
# Engineer requests emergency access
vkit request \
--datasource production_db \
--approval-required \
--reason "Investigating payment failure - Ticket INC-5432" \
--metadata '{"incident_ticket": "INC-5432", "business_justification": "Payment processor reporting transaction mismatch"}' \
--aql '{
"source_table": "transactions",
"columns": ["transaction_id", "amount", "status"],
"filters": [{"field": "status", "operator": "eq", "value": "failed"}]
}'
# Finance manager approves
vkit approval grant \
--request-id req_20240115_xyz789 \
--notes "Approved for incident resolution."
# Engineer fetches data
vkit fetch --grant grant_approved_abc123
Audit Trail Output:
{
"request_id": "req_20240115_xyz789",
"requester": "engineer@company.com",
"requester_role": "engineer",
"requested_at": "2024-01-15T16:00:00Z",
"approved_by": "finance.manager@company.com",
"approved_at": "2024-01-15T16:05:32Z",
"access_expires": "2024-01-15T18:05:32Z",
"queries_executed": 3,
"rows_accessed": 147,
"incident_ticket": "INC-5432",
"auto_revoked": true
}
Every query execution generates a signed audit record:
{
"audit_id": "audit_20240115_abc123",
"timestamp": "2024-01-15T16:30:45Z",
"requester": {
"user_id": "user_12345",
"email": "analyst@company.com",
"role": "analyst",
"clearance_level": 2,
"region": "US"
},
"request": {
"datasource_id": "production_db",
"dataset": "customers",
"columns_requested": ["id", "email", "revenue"]
},
"policy_evaluation": {
"policies_applied": [
{
"policy_id": "analyst_basic_access",
"action": "mask",
"fields_affected": ["email"],
"mask_type": "partial"
}
],
"access_granted": true
},
"execution": {
"execution_time_ms": 245,
"rows_returned": 47
},
"metadata": {
"grant_id": "grant_def789",
"ttl_expires": "2024-01-16T00:30:45Z"
}
}
audit:
sinks:
- type: postgres
name: primary
- type: s3
name: archive
bucket: audit-archive
retention_days: 2555
- type: webhook
name: security_monitoring
url: https://siem.company.com/events
# Authentication
vkit login
vkit logout
# Datasource Management
vkit datasource add
vkit datasource list
vkit datasource test --id <id>
vkit datasource remove --id <id>
# Schema Discovery
vkit scan <datasource_id>
vkit scan --all
vkit scan <id> --apply
vkit scan <id> --diff
# Policy Management
vkit policy init --repo <path>
vkit policy validate
vkit policy bundle
vkit policy deploy
vkit policy list
# Data Access
vkit request
vkit fetch --grant <grant_id>
vkit cancel --grant <grant_id>
# Approvals
vkit approval list
vkit approval grant --request <id>
vkit approval deny --request <id>
# Audit
vkit audit query
vkit audit export
# Administration
vkit user list
vkit user create
vkit session list
vkit session revoke --id <session>
DO:
DO NOT:
DO:
DO NOT:
DO:
DO NOT:
VaultKit is licensed under the Apache License 2.0. See LICENSE for details.
VaultKit is built with and inspired by:
Built with ❤️ by the VaultKit team