Metadata-Version: 2.4
Name: aperture-ai
Version: 0.2.0
Summary: The permission layer for AI agents. Controls what passes through.
Project-URL: Homepage, https://github.com/adnanzaib/aperture-ai
Project-URL: Repository, https://github.com/adnanzaib/aperture-ai
Project-URL: Issues, https://github.com/adnanzaib/aperture-ai/issues
Project-URL: Documentation, https://github.com/adnanzaib/aperture-ai#readme
Author: Adnan Zaib
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: agents,ai,audit,mcp,permissions,rbac,security
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: fastapi>=0.115.0
Requires-Dist: mcp>=1.2.0
Requires-Dist: pydantic-settings>=2.6.0
Requires-Dist: pydantic>=2.10.0
Requires-Dist: sqlmodel>=0.0.22
Requires-Dist: uvicorn[standard]>=0.32.0
Provides-Extra: dev
Requires-Dist: httpx>=0.27.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Description-Content-Type: text/markdown

# Aperture

**The permission layer for AI agents.**

AI agents can run shell commands, read your files, call APIs, and modify databases. Today, you're the only thing standing between an agent and `rm -rf /`. Every action gets a yes/no popup. You either approve everything blindly or slow your workflow to a crawl.

Aperture fixes this. It sits between your agent runtime and the outside world, learns your permission preferences over time, and auto-approves the safe stuff — so you only get asked about things that actually matter.

> **Setup guides:** [Claude Code](docs/setup-claude-code.md) | [OpenClaw](docs/setup-openclaw.md) | [REST API](#rest-api) | [Python library](#python-library)

## How it works

```
┌──────────────────────────────────────────────────────────────────┐
│                      Your Agent Runtime                          │
│           (Claude Code, OpenAI Agents, LangChain, etc.)          │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       │  "Can this agent run `npm test`?"
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│                         APERTURE                                 │
│                                                                  │
│   ┌─────────────┐  ┌──────────────┐  ┌───────────────────────┐  │
│   │ Permission   │  │ Risk Scoring │  │ Learning Engine       │  │
│   │ Engine       │  │              │  │                       │  │
│   │              │  │ tool danger  │  │ You approved npm test │  │
│   │ RBAC rules   │─▶│ × action     │  │ 15 times in a row.   │  │
│   │ Task grants  │  │   severity   │  │ Auto-approving now.   │  │
│   │ Learned      │  │ × scope      │  │                       │  │
│   │   patterns   │  │   breadth    │  │ You denied rm -rf /   │  │
│   │              │  │              │  │ every time.            │  │
│   └──────┬───┬──┘  └──────────────┘  │ Auto-denying now.     │  │
│          │   │                        └───────────────────────┘  │
│          │   │     ┌──────────────┐  ┌───────────────────────┐  │
│          │   │     │ Audit Trail  │  │ Artifact Store        │  │
│          │   └────▶│ Every        │  │ SHA-256 verified      │  │
│          │         │ decision     │  │ immutable storage     │  │
│          │         │ logged       │  │ for agent outputs     │  │
│          │         └──────────────┘  └───────────────────────┘  │
└──────────┼───────────────────────────────────────────────────────┘
           │
           ▼
     ┌─────────────┐
     │  ALLOW       │  ← auto-approved (learned pattern)
     │  DENY        │  ← auto-denied (learned pattern)
     │  ASK         │  ← no pattern yet, ask the human
     └─────────────┘
```

**No LLM calls.** Every decision is deterministic — glob matching, statistics, and pattern lookup. Aperture never phones home, never calls an API, and adds zero latency from model inference.

## What you experience

**Day 1** — Aperture asks you about everything, just like today. But it's recording your decisions.

**Day 3** — You've approved `npm test`, `git status`, and `cat README.md` a dozen times each. Aperture stops asking about those. You still get prompted for `rm`, `curl`, and anything touching production.

**Day 7** — The only popups you see are for genuinely new or risky actions. Everything routine is auto-approved. Everything dangerous is auto-denied. Your agent moves faster and you have a full audit trail of every decision.

## Quick start

```bash
pip install aperture-ai       # Install from PyPI
aperture init-db              # Initialize the database
aperture serve                # Start the API server on localhost:8100
```

That's it. Aperture is running. Now connect your agent runtime.

## Connect your runtime

### Claude Code (MCP)

Add to your `.mcp.json`:

```json
{
  "mcpServers": {
    "aperture": {
      "type": "stdio",
      "command": "aperture",
      "args": ["mcp-serve"]
    }
  }
}
```

This gives Claude Code 9 tools including `check_permission`, `approve_action`, `deny_action`, `store_artifact`, and `get_audit_trail`.

**[Full Claude Code setup guide →](docs/setup-claude-code.md)**

### OpenClaw

Add Aperture as OpenClaw's MCP permission server:

```json
{
  "mcpServers": {
    "aperture": {
      "command": "aperture",
      "args": ["mcp-serve"],
      "env": {
        "APERTURE_DB_PATH": "./aperture.db"
      }
    }
  }
}
```

Add a [system prompt](examples/system_prompt.md) that tells the agent to call `check_permission` before every action, then `openclaw chat`.

**[Full OpenClaw setup guide →](docs/setup-openclaw.md)**

### REST API

Any agent runtime can use the HTTP API:

```bash
# Check a permission
curl -X POST localhost:8100/permissions/check \
  -H "Content-Type: application/json" \
  -d '{"tool": "shell", "action": "execute", "scope": "npm test"}'

# Record a human decision (feeds the learning engine)
curl -X POST localhost:8100/permissions/record \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "shell", "action": "execute", "scope": "npm test",
    "decision": "allow", "decided_by": "user-1"
  }'
```

### Python library

```python
from aperture.permissions import PermissionEngine
from aperture.models import PermissionDecision

engine = PermissionEngine()

# Check if an action is allowed
verdict = engine.check("shell", "execute", "npm test", rules=[])

# Record a human decision
engine.record_human_decision(
    tool="shell", action="execute", scope="npm test",
    decision=PermissionDecision.ALLOW, decided_by="user-1",
    organization_id="my-org",
)

# After enough decisions, the engine auto-approves
verdict = engine.check("shell", "execute", "npm test", rules=[])
print(verdict.decision)  # PermissionDecision.ALLOW
```

## Features

| Feature | What it does |
|---------|-------------|
| **Permission Engine** | RBAC rules + task-scoped grants (ReBAC) + auto-learning from human decisions |
| **Risk Scoring** | OWASP-inspired `tool danger × action severity × scope breadth` — flags `rm -rf /` as CRITICAL, `cat README.md` as LOW |
| **Learning Engine** | Tracks your approval/denial history per (tool, action, scope). After 10+ consistent decisions, auto-decides |
| **Crowd Wisdom** | Aggregates decisions across your org — surfaces what your team usually approves or denies |
| **Artifact Store** | SHA-256 verified, immutable storage for every agent output |
| **Audit Trail** | Append-only compliance log of every permission decision |
| **MCP Server** | 9 tools for Claude Code via Model Context Protocol |
| **REST API** | FastAPI server for any agent runtime |
| **CLI** | `aperture serve`, `aperture init-db`, `aperture configure` |

## How decisions are made

Aperture resolves permissions in this order, stopping at the first match:

```
1. Session memory     →  Already decided this session? Reuse it.
2. Task grants (ReBAC) →  Scoped permission for this specific task?
3. Learned patterns   →  10+ consistent human decisions? Auto-decide.
4. Static RBAC rules  →  Glob-matched rules (most specific wins).
5. Default deny       →  No match? Deny.
```

When enrichment is enabled, each verdict also includes:
- **Risk assessment** — tier (LOW/MEDIUM/HIGH/CRITICAL), score, factors, reversibility
- **Human-readable explanation** — what the action does, in plain English
- **Crowd signal** — what your org has historically decided for this pattern
- **Similar patterns** — related decisions that might inform this one
- **Recommendation** — auto-approve, auto-deny, suggest a rule, or keep asking

<details>
<summary><strong>Configuration</strong></summary>

All settings via environment variables (prefix `APERTURE_`):

| Variable | Default | Description |
|---|---|---|
| `APERTURE_DB_BACKEND` | `sqlite` | `sqlite` or `postgres` |
| `APERTURE_DB_PATH` | `aperture.db` | SQLite file path |
| `APERTURE_POSTGRES_URL` | — | Postgres connection URL |
| `APERTURE_PERMISSION_LEARNING_ENABLED` | `true` | Auto-learn from human decisions |
| `APERTURE_PERMISSION_LEARNING_MIN_DECISIONS` | `10` | Min decisions before auto-deciding |
| `APERTURE_AUTO_APPROVE_THRESHOLD` | `0.95` | Approval rate to trigger auto-approve |
| `APERTURE_AUTO_DENY_THRESHOLD` | `0.05` | Approval rate to trigger auto-deny |
| `APERTURE_INTELLIGENCE_ENABLED` | `false` | Cross-org intelligence (opt-in) |
| `APERTURE_API_HOST` | `0.0.0.0` | API bind host |
| `APERTURE_API_PORT` | `8100` | API bind port |

Or run `aperture configure` for an interactive setup wizard.

</details>

<details>
<summary><strong>Development</strong></summary>

```bash
pip install -e ".[dev]"
python -m pytest tests/ -v
```

Requires Python 3.12+.

</details>

## License

Apache 2.0 — see [LICENSE](LICENSE).
