Skip to main content
Glama
README.md
# Acutis Gate

**Identity-based access control for AI.** Every tool call an AI makes runs as the person who asked, under guardrails you wrote, with the full call recorded in a tamper-evident trail that streams to your SIEM. Works with cloud AI and local models, with modern apps and the systems you already run.

Gate is one small service that sits between any MCP client (Open WebUI on a local model, Claude Desktop, Cursor, Microsoft Copilot, your own agents) and the MCP servers that reach your systems. It is the only tool server your AI clients need to know about.

```
  Open WebUI / Claude Desktop / Cursor / Copilot
                    │  MCP (streamable HTTP) + personal token
                    ▼
            ┌───────────────┐   identity · guardrails · data filter · audit chain
            │  Acutis Gate  │──────────────────────────────────────► your SIEM
            └───────────────┘
                    │  as the person (their key, token or session)
                    ▼
     your MCP servers: files, firewall, HR, CRM, databases, Active Directory …
```

## Three promises

1. **Attributed.** Every call is tied to a real person. When a system can only take a shared account, the audit row says so. No anonymous "the AI did it".
2. **Fenced.** Rules you wrote decide what each person's AI may read, change or run, and which actions wait for an approver. Explicit deny always wins. Locked rules need an authenticator code to change.
3. **Recorded.** Everything, hash-chained: full arguments and results, what each AI was shown, failed sign-ins, every policy and identity change. Streamed live to syslog (JSON or CEF), a signed webhook, or Splunk HEC. One click proves nothing was edited.

What Gate never claims: it does not detect intent, it does not decide on its own that something "needs escalating" (approvals are rules you write, like change control), and it cannot see AI calls that bypass it. The companion control is a firewall rule that makes Gate the only tool server your AI clients can reach.

## Quick start (5 minutes)

```bash
git clone https://github.com/gspam100/acutis-gate.git && cd acutis-gate
cp .env.example .env            # fill the three secrets: python -c "import secrets; print(secrets.token_hex(32))"
python3.12 -m venv .venv && . .venv/bin/activate && pip install -r requirements.txt
python -m gate.cli init-admin --org "Your Org" --email you@yourcompany.com
uvicorn gate.main:app --port 8010
```

Open http://localhost:8010/gate, sign in, enroll your authenticator, go to **Connect an AI** and mint a token. Then point any MCP client at `http://localhost:8010/api/v1/gate/mcp` with `Authorization: Bearer <token>`. The console shows the exact config for Claude Desktop, Cursor and Open WebUI.

Try it with the demo upstream in `examples/demo-upstream/` (a pretend firewall that proves per-user delegation).

One box with Docker, Postgres, a local model and Open WebUI: `sudo LOCAL_AI=1 bash deploy/install.sh`.

## Learning mode

A fresh Gate allows everything and records everything. Let people work for a few days, then open **Guardrails → Build rules from the trail**. Gate drafts one *allow* rule per group and app for the reads it saw, and one *needs approval* rule for the changes it saw. Review, edit, save. From that version on, anything the trail never saw is denied, and an explicit deny always wins.

## What is in the box

- **MCP endpoint** (`/api/v1/gate/mcp`): stateless streamable HTTP. `tools/list` is filtered per person; `tools/call` is evaluated, executed under that person's identity, and recorded.
- **Delegated execution**: an upstream call carries the person's own key (`user_key`), their bearer token (`passthrough`), or a labelled shared service secret (`service`, recorded as `mapped` so an auditor can see which calls were not per-user).
- **Guardrails**: deny-by-default rule engine with `allow`, `deny`, `approve` and `break_glass`; `who` by role, group or person; `do` read/write/execute; `on` resource globs like `files://finance/**`; `except`; `locked` rules that need an authenticator code to change; dry-run; versioned with history; test-as-person.
- **Approvals**: a staged call keeps its exact arguments; an approver (never the requester) reviews them with an authenticator code; it runs as the original person.
- **Data filter**: payment cards (Luhn-checked), SSNs, API keys and cloud secrets redacted from results before the model sees them; emails and phones optional; or block the whole result. Counts in the audit row, never the values.
- **Audit chain**: SHA-256 chained per organization; stores full arguments and results (capped, hashed in full before truncation); every console and sign-in event in the same chain; `verify` names the first edited row.
- **Streaming**: syslog UDP/TCP/TLS (RFC 5424, JSON or CEF), HTTPS webhook with HMAC signature, Splunk HTTP Event Collector; NDJSON export with a cursor; Server-Sent Events live tail.
- **Identity**: email + password + authenticator (mandatory), Google Workspace sign-in per organization, roles admin/technician/viewer, groups. Kerberos from a domain PC, ADFS/SAML, Entra ID, Okta and RADIUS are on the roadmap.
- **Console**: one page per job. Connect an AI, My apps, Approvals, Audit trail; for admins Identity, Guardrails, Groups, Streaming.

## Configuration

| Variable | Required | Meaning |
|---|---|---|
| `JWT_SECRET`, `SECRET_KEY`, `VAULT_MASTER_KEY` | yes | session signing; reserved; encryption of stored credentials at rest |
| `PUBLIC_BASE_URL` | yes | where people reach Gate (emails, CORS) |
| `DATABASE_URL` | prod | Postgres. Or `ACUTIS_ALLOW_SQLITE=1` for one box |
| `GOOGLE_OAUTH_CLIENT_ID` | no | enables "Sign in with Google" (per-organization switch in the console) |
| `SMTP_*` | no | password and authenticator recovery emails; unset prints to stdout |
| `TRUSTED_PROXY_HOPS` | no | how many reverse proxies set X-Forwarded-For |

Upgrading an existing install: `python deploy/migrate.py` adds any new columns (tables are created automatically).

## Security

Read `SECURITY.md` for the threat model and how to report a vulnerability. Short version: passwords are PBKDF2 with 260k rounds; TOTP enrollment is mandatory for local accounts; sensitive actions require a fresh single-use code; stored credentials are AES-GCM under `VAULT_MASTER_KEY`; sign-in paths are rate limited; tool output is data, never instructions; writes and executes can be staged behind a human.

## Development

```bash
pip install -r requirements-dev.txt
python -m pytest
```

Tests cover the resource grammar, the policy engine, the audit chain and payload tampering, the MCP endpoint, delegation modes, approvals, break-glass, dry run, the data filter, learning mode, SIEM sinks (a real UDP receiver and a signed webhook), and the NDJSON export.

## License

AGPL-3.0. Run it, change it, ship it; if you offer a modified Gate as a service, share your changes. A commercial license, hosted edition, signed installers and enterprise identity connectors are available from Acutis: https://acutisgo.com/gate/

Maintenance

ActivityMaintained
ResponsivenessNo issues