# Policies
Policies define access rules for your AI tools. SolonGate uses default-deny — all tool calls are blocked unless explicitly allowed by a matching rule. Policies work alongside the prompt injection detector and AI Judge in the 5-step security pipeline.
How it works: Rules are evaluated in priority order (lowest number = highest priority). The first matching rule decides the outcome. If no rule matches, the request is DENYed.
Policy JSON Structure
A policy is a JSON object with a name, version, and an array of rules. This is the exact format used by the dashboard, proxy CLI, and API. Each rule uses one constraint type to target a specific aspect of tool calls.
1{2 "name": "Production Policy",3 "version": 1,4 "rules": [5 {6 "id": "block-dangerous-commands",7 "effect": "DENY",8 "permission": "EXECUTE",9 "minimumTrustLevel": "UNTRUSTED",10 "priority": 10,11 "commandConstraints": {12 "denied": ["npm*", "py*", "rm -rf*", "sudo*"]13 },14 "description": "Block npm, python, rm -rf, and sudo"15 },16 {17 "id": "block-sensitive-files",18 "effect": "DENY",19 "permission": ["READ", "WRITE", "DELETE"],20 "minimumTrustLevel": "UNTRUSTED",21 "priority": 20,22 "filenameConstraints": {23 "denied": [".env", "*.key", "*.pem"]24 },25 "description": "Block access to secrets and credentials"26 },27 {28 "id": "block-restricted-paths",29 "effect": "DENY",30 "permission": ["READ", "WRITE", "MOVE", "DELETE"],31 "minimumTrustLevel": "UNTRUSTED",32 "priority": 30,33 "pathConstraints": {34 "denied": ["**/secrets/**", "**/private/**"]35 },36 "description": "Block restricted directories"37 },38 {39 "id": "block-social-media",40 "effect": "DENY",41 "permission": "READ",42 "minimumTrustLevel": "UNTRUSTED",43 "priority": 40,44 "urlConstraints": {45 "denied": ["*instagram.com*", "*facebook.com*"]46 },47 "description": "Block social media URLs"48 },49 {50 "id": "allow-everything-else",51 "effect": "ALLOW",52 "minimumTrustLevel": "UNTRUSTED",53 "priority": 1000,54 "description": "Allow everything not blocked above"55 }56 ]57}
Rule Fields
| Field | Required | Description |
|---|---|---|
| id | Yes | Unique rule identifier |
| permission | No | READ, WRITE, EXECUTE, MOVE, or DELETE. If omitted, rule applies to all permission types |
| effect | Yes | ALLOW or DENY |
| minimumTrustLevel | Yes | UNTRUSTED, VERIFIED, or TRUSTED |
| priority | Yes | 0–10000. Lower = evaluated first |
| description | No | Human-readable description |
Constraint Types
Constraints narrow what a rule matches. If a constraint is set and the tool call violates it, the rule does not match and evaluation continues to the next rule.
| Constraint | Fields | Use Case |
|---|---|---|
| commandConstraints | allowed, denied | Allow/block specific shell commands |
| filenameConstraints | allowed, denied | Filter by file extension or name pattern |
| pathConstraints | allowed, denied, rootDirectory, allowSymlinks | Restrict file system access paths |
| urlConstraints | allowed, denied | Control which URLs can be fetched |
Constraint Examples
Each constraint type targets a different aspect of tool calls. Below are practical examples showing how to write rules for each type. Use glob patterns (* for wildcards) in constraint values.
commandConstraintsBlock or allow shell commands
Matches the command argument in shell_exec tool calls. Use denied to block dangerous commands, or allowed to whitelist safe ones.
1// DENY rule: block npm and python commands2{3 "id": "block-dangerous-commands",4 "effect": "DENY",5 "permission": "EXECUTE",6 "minimumTrustLevel": "UNTRUSTED",7 "priority": 10,8 "commandConstraints": {9 "denied": ["npm*", "py*", "rm -rf*", "sudo*"]10 },11 "description": "Block npm, python, rm -rf, and sudo"12}1314// ALLOW rule: only allow safe commands15{16 "id": "allow-safe-commands",17 "effect": "ALLOW",18 "permission": "EXECUTE",19 "minimumTrustLevel": "VERIFIED",20 "priority": 200,21 "commandConstraints": {22 "allowed": ["git*", "ls*", "cat*", "grep*", "node*"]23 },24 "description": "Only allow git, ls, cat, grep, node"25}
Test: With the DENY rule above, running npm install express or python3 script.py will be blocked. Running git status will pass through (no match on the deny rule).
filenameConstraintsBlock or allow specific file names
Matches the filename (basename) extracted from path, file_path, or filename arguments. Useful for blocking access to sensitive files regardless of their directory.
1// Block .env files, private keys, and specific files2{3 "id": "block-sensitive-files",4 "effect": "DENY",5 "permission": ["READ", "WRITE", "DELETE"],6 "minimumTrustLevel": "UNTRUSTED",7 "priority": 20,8 "filenameConstraints": {9 "denied": [".env", "*.pem", "*.key", "credentials.json", "secrets.yaml"]10 },11 "description": "Block access to secrets and credentials"12}
Test: Reading /home/user/project/.env or /any/path/server.key will be blocked. Reading /home/user/project/index.ts will pass through.
pathConstraintsRestrict file system access by path
Matches the full file path from arguments. Use denied to block specific directories, allowed to whitelist paths, and rootDirectory to enforce a base directory. Patterns use glob syntax with ** for recursive matching.
Path Pattern Reference
There are 4 ways to write path patterns. ** must be its own path segment — always separated by / or \. Never attach it directly to a filename or directory name.
| Pattern | What it does | Example matches |
|---|---|---|
| C:\Users\HP\secret.txt | Exact file path | Only that specific file |
| C:\Users\HP\private\** | Everything inside a directory | All files and subfolders under private\ |
| **\SECRET.md | File by name, anywhere | Any file named SECRET.md regardless of directory |
| **\private\** | Directory by name, anywhere | Any private\ folder at any depth |
Common mistake: **secret.txt does NOT work. ** must be a standalone segment separated by slashes. Write **/secret.txt instead.
JSON escaping: In JSON files, backslashes must be doubled. The path C:\Users\HP\private\** is written as "C:\\Users\\HP\\private/**" in JSON. Forward slashes also work: "C:/Users/HP/private/**".
1// Block access to specific directories and files2{3 "id": "block-restricted-paths",4 "effect": "DENY",5 "permission": ["READ", "WRITE", "MOVE", "DELETE"],6 "minimumTrustLevel": "UNTRUSTED",7 "priority": 30,8 "pathConstraints": {9 "denied": [10 "C:\\Users\\HP\\private/**",11 "**/secrets/**",12 "**/TEST_REHBERI.md"13 ]14 },15 "description": "Block access to private dir, secrets, and TEST_REHBERI.md"16}1718// Allow only within a project directory19{20 "id": "allow-project-files",21 "effect": "ALLOW",22 "permission": ["READ", "WRITE"],23 "minimumTrustLevel": "VERIFIED",24 "priority": 100,25 "pathConstraints": {26 "rootDirectory": "/home/user/project",27 "denied": ["**/node_modules/**", "**/.git/**"],28 "allowSymlinks": false29 },30 "description": "Allow file access only within project root"31}
Test: With the DENY rule above, reading C:\Users\HP\private\notes.txt or any file named TEST_REHBERI.md will be blocked. Reading C:\Users\HP\project\src\index.ts will pass through.
urlConstraintsControl which URLs can be fetched
Matches the url argument in web_fetch and similar tools. Use to prevent data exfiltration or block access to unwanted domains.
1// Block social media and untrusted domains2{3 "id": "block-social-media",4 "effect": "DENY",5 "permission": "READ",6 "minimumTrustLevel": "UNTRUSTED",7 "priority": 40,8 "urlConstraints": {9 "denied": [10 "*instagram.com*",11 "*facebook.com*",12 "*tiktok.com*",13 "http://**"14 ]15 },16 "description": "Block social media and insecure HTTP"17}1819// Only allow trusted API endpoints20{21 "id": "allow-trusted-apis",22 "effect": "ALLOW",23 "permission": "READ",24 "minimumTrustLevel": "VERIFIED",25 "priority": 100,26 "urlConstraints": {27 "allowed": [28 "https://api.github.com/**",29 "https://registry.npmjs.org/**"30 ]31 },32 "description": "Only allow GitHub and npm APIs"33}
Test: Fetching https://instagram.com/api/user or http://evil.com/steal will be blocked. Fetching https://api.github.com/repos is allowed.
Combining Multiple Constraints
A real policy typically has multiple DENY rules (one per constraint type) followed by ALLOW rules. DENY rules should have lower priority numbers (evaluated first) so they block before any ALLOW rule matches.
1{2 "name": "Production Policy",3 "version": 1,4 "rules": [5 {6 "id": "block-dangerous-commands",7 "effect": "DENY",8 "permission": "EXECUTE",9 "minimumTrustLevel": "UNTRUSTED",10 "priority": 10,11 "commandConstraints": {12 "denied": ["npm*", "py*", "rm -rf*", "sudo*"]13 },14 "description": "Block dangerous commands"15 },16 {17 "id": "block-sensitive-files",18 "effect": "DENY",19 "permission": ["READ", "WRITE", "DELETE"],20 "minimumTrustLevel": "UNTRUSTED",21 "priority": 20,22 "filenameConstraints": {23 "denied": [".env", "*.key", "*.pem"]24 },25 "description": "Block sensitive files"26 },27 {28 "id": "block-restricted-paths",29 "effect": "DENY",30 "permission": ["READ", "WRITE", "MOVE", "DELETE"],31 "minimumTrustLevel": "UNTRUSTED",32 "priority": 30,33 "pathConstraints": {34 "denied": ["**/secrets/**", "**/private/**"]35 },36 "description": "Block restricted directories"37 },38 {39 "id": "block-social-media",40 "effect": "DENY",41 "permission": "READ",42 "minimumTrustLevel": "UNTRUSTED",43 "priority": 40,44 "urlConstraints": {45 "denied": ["*instagram.com*", "*facebook.com*"]46 },47 "description": "Block social media"48 },49 {50 "id": "allow-all-verified",51 "effect": "ALLOW",52 "minimumTrustLevel": "UNTRUSTED",53 "priority": 1000,54 "description": "Allow everything else"55 }56 ]57}
Pattern: DENY rules at priority 10–40 catch dangerous operations first. The catch-all ALLOW at priority 1000 lets everything else through. Without the final ALLOW, the default-deny fallback would block all uncovered tool calls.
Trust Levels & Permissions
Trust Levels
UNTRUSTEDUnknown source — matches all callersVERIFIEDValid API key — default for productionTRUSTEDInternal/admin — use sparinglyPermissions
READFile reads, queries, fetchesWRITEFile writes, inserts, postsEXECUTEShell commands, code evalMOVEFile/directory rename and move operationsDELETEFile/directory deletionPriority System
Rules are sorted by priority (ascending, 0–10000). Lower numbers are evaluated first. The first matching rule wins.
1// Priority convention:2// 0–49: Critical security blocks (always deny dangerous tools)3// 50–99: High-priority overrides4// 100–499: Standard allow/deny rules5// 500–999: Fallback rules6// 1000: Default priority (if not specified)
Proxy CLI — pull, push, list
The proxy CLI lets you manage policies from the command line. Requires a sg_live_ key (set via SOLONGATE_API_KEY env var or --api-key flag).
1# List all your policies2npx @solongate/proxy@latest list34# Show details of a specific policy5npx @solongate/proxy@latest list --policy-id <policy ID>67# Pull a policy from the cloud → saves to policy.json by default8npx @solongate/proxy@latest pull --policy-id <policy ID>910# Push a local policy.json to the cloud11npx @solongate/proxy@latest push --policy-id <policy ID>1213# Aliases: ls = list, --id = --policy-id
pull
Downloads your policy from the cloud and saves it as a local JSON file (default: policy.json). If you omit --policy-id, it lists available policies and lets you choose.
push
Uploads a local JSON file to the cloud. If the policy already exists, it updates it (auto-increments version). If it doesn't exist, it creates a new one.--policy-id is required.
list
Shows all your policies with name, version, rule count, and last updated time. Use --policy-id to see details of a specific policy.
Policy Versioning & Rollback
Every policy change creates a new version with a SHA-256 hash. The full version history is available in the dashboard — you can rollback to any previous version with one click.
How versioning works
- Every save or push creates a new immutable version (append-only)
- Each version gets a SHA-256 hash for integrity verification
- Rollback doesn't delete history — it creates a new version with the old policy data
- Full audit trail: who changed what, when, and why
Rollback: Go to dashboard.solongate.com/policies → click the history icon on any policy → select a version → click "Rollback to vX".
Testing Your Policy
After creating a policy, test it by asking your AI client to perform these actions through the proxy. Each test targets a specific constraint type. Use the example policy above as reference.
| # | Test Action | Constraint | Expected |
|---|---|---|---|
| 1 | shell_exec: npm install express | command | DENY |
| 2 | shell_exec: python3 script.py | command | DENY |
| 3 | shell_exec: git status | command | ALLOW |
| 4 | file_read: /project/.env | filename | DENY |
| 5 | file_read: /project/src/index.ts | filename | ALLOW |
| 6 | file_read: /home/secrets/api-key.txt | path | DENY |
| 7 | file_read: /home/user/project/README.md | path | ALLOW |
| 8 | web_fetch: https://instagram.com/api | url | DENY |
| 9 | web_fetch: https://facebook.com/graph | url | DENY |
| 10 | web_fetch: https://api.github.com/repos | url | ALLOW |
Tip: Start the proxy with your policy, then use Claude Code (or any AI client) connected through the proxy. Try each action above and verify the proxy logs show the correct ALLOW/DENY decision.