Metadata-Version: 2.4
Name: tollgate-gateway
Version: 0.1.4
Summary: Tollgate — the governance gate for AI agents that move money (确定性治理网关:策略裁决/人工审批/预算预留/审计哈希链)
Author: Tollgate contributors
License: Apache-2.0
Project-URL: Homepage, https://github.com/kkU1444/tollgate
Project-URL: Issues, https://github.com/kkU1444/tollgate/issues
Project-URL: Threat-Model, https://github.com/kkU1444/tollgate/blob/main/THREAT_MODEL.md
Keywords: ai,agent,governance,security,llm,mcp,audit,fintech
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: live
Requires-Dist: openai>=1.40; extra == "live"
Provides-Extra: yaml
Requires-Dist: pyyaml>=6.0; extra == "yaml"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Dynamic: license-file

# Tollgate — the governance gate for AI agents that move money

![CI](https://github.com/kkU1444/tollgate/actions/workflows/ci.yml/badge.svg)
![License](https://img.shields.io/badge/license-Apache--2.0-blue)
![Python](https://img.shields.io/badge/python-3.10%2B-blue)
![Dependencies](https://img.shields.io/badge/dependencies-0-success)

> Deterministic policy enforcement, human approvals with cryptographic
> non-repudiation, budget escrow with clawback, and a tamper-evident audit
> chain — a **zero-dependency** governance gateway for any agent that touches
> money. Exposed to any agent as an **MCP server**.

[![PyPI](https://img.shields.io/pypi/v/tollgate-gateway)](https://pypi.org/project/tollgate-gateway/)
[![Python](https://img.shields.io/pypi/pyversions/tollgate-gateway)](https://pypi.org/project/tollgate-gateway/)
[![CI](https://img.shields.io/github/actions/workflow/status/kkU1444/tollgate/ci.yml?branch=main&label=tests)](https://github.com/kkU1444/tollgate/actions/workflows/ci.yml)
[![Zero dependencies](https://img.shields.io/badge/dependencies-zero-brightgreen)](#install)
[![License](https://img.shields.io/github/license/kkU1444/tollgate)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-server-blue)](#mcp-server)

[中文文档](README.zh-CN.md)

**Axiom:** the LLM is an untrusted component. It proposes; deterministic code
disposes. Every tool call an agent makes passes through the gate — and the
gate never guesses.

## Why

Teams won't give agents spending authority because three questions have no
answer: *what exactly can it do? who is accountable? can we audit it
afterwards?* Tollgate answers all three with a single enforcement point that
every tool call must cross:

```
unknown tool → rate limit → circuit breaker → integrity check → read cache
→ accountability → blacklist → budget reserve → field-semantics contract
→ injection fence → financial guardrails → adaptive risk score
→ policy rules (with business-calendar context) → authenticated approval
→ execution → hash-chained audit
```

Denial reasons flow back to the model so it can adapt. Anything that isn't
explicitly allowed is denied — and that default is *measured*, not assumed
(see [Red team](#red-team)).

## 60-second demo

```bash
git clone https://github.com/kkU1444/agent-governance-gateway.git && cd agent-governance-gateway
python -m tollgate demo-web        # no API key needed
# open http://127.0.0.1:8765 — approve the $4,200 transfer in the browser
```

A travel agent runs a 15-step adversarial scenario: read-only calls pass,
external email is blocked, a replayed payment is caught, a negative amount is
rejected, an unregistered agent is refused, an unknown payee forces human
sign-off, and an over-limit transfer hits a hard cap. Then the ops team
freezes and claws back a fraudulent transfer, and the payee lands on a
blocklist.

## The money lifecycle

Approving a transfer is not the same as money leaving the building:

```
reserve (atomic, concurrency-safe) → human approval → execution
→ holding period (24h, funds in escrow, reversible)
→ settle | freeze → recover (clawback) → payee blacklist (permanent escalation)
```

Budget pools use `BEGIN IMMEDIATE` critical sections so concurrent agents see
"occupied", not a stale balance. Clawbacks are two-step (freeze, then
recover), each with operator identity and reason written into the audit
chain.

## Security architecture

| Threat | Mechanism |
|---|---|
| Prompt injection | deterministic fence + pattern guard + **canary tokens** planted in context (a canary in tool args is *proof* of hijack → hard deny) |
| Semantic misreading (`risk_score: 0.87` read as "high confidence") | **field-semantics contract** — meaning and thresholds of risk fields are owned by code; upstream risk signals auto-flag payees |
| Model hallucination / loops | forced replanning protocol, loop breaker, goal-anchored compaction |
| Concurrency / stale state | atomic budget reservation (BEGIN IMMEDIATE) |
| Rogue or unattributed agents | accountability registry — no registered owner, no execution; per-agent caps; approver authority levels |
| Forged approvals | HMAC or **Ed25519** signatures (pure-Python RFC 8032); private keys stay with approvers; `verify-approval` recomputes; four-eyes for large amounts |
| Tool supply-chain tampering | registration/runtime tool fingerprints vs sealed baseline |
| Credential theft | credential broker issues per-call, short-lived scoped credentials; secret scanning masks leaks in args/results |
| Audit tampering | SQLite hash chain + `verify` locates the exact tampered row; policy hot-reloads are themselves chain-anchored |
| Resource exhaustion (DoS) | per-agent sliding-window rate limits (money is capped by budget breakers, compute by rate limits) |

Policy files hot-reload on change; every reload lands in the chain as a
`policy.reload` entry (old hash → new hash), so *changes to the law itself*
are auditable.

**Learning loop:** attacks are auto-recorded into an intel base, replayed on
every change (`tollgate drill`), and live samples merge into the red-team corpus
(`tollgate redteam`) — real attacks become permanent regression tests.

## Red team

```bash
$ python -m tollgate redteam
恶意样本拦截: 32/32 (召回率 100%)      injection corpus: 32/32 blocked
良性样本误报: 0/8 (误报率 0%)          false positives: 0/8
策略不变量模糊测试: 300 例,四条不变量全部成立   300 fuzz cases, all invariants hold
```

Four fuzz invariants: the governance layer never crashes; execution is
fail-closed (actual executions ≡ audited executions); the hash chain survives
any input sequence; same seed reproduces exactly. [THREAT_MODEL.md](THREAT_MODEL.md)
maps mechanisms to STRIDE, OWASP Agentic AI threats and MITRE ATLAS, and keeps
an honest residual-risk list.

## TollgateBench

A five-dimension benchmark for the governance layer itself — answer-key
scoring, binary gates, exit code as the release gate:

```bash
$ python -m tollgate bench
TollgateBench v0.1.0 — 治理网关统一基准
========================================================================
被测对象: tollgate 0.1.3   种子: 42   平台: 3.15.0/Windows   耗时: 3.04s

[D1] 决策正确性   ✓ 24/24 (门槛: pass_rate == 1.0(治理正确性是二元的))
[D2] 注入检测     ✓ 召回 32/32 (100%), 误报 0/8 (0%)
[D3] 不变量       ✓ 300 例 × 2 轮, 同种子可复现: True
[D4] 审计完整性   ✓ 3/3 (链完整 / 篡改定位 / 检查点锚定)
[D5] 治理开销     ✓ 全链 p50 0.118ms / p99 0.542ms, 吞吐 ~5,837 ops/s
                  无治理直调 mean 0.0004ms → 治理开销 +0.1709ms/次 (×433.4)
========================================================================
裁决: PASS (5/5 门槛通过)
```

Decision correctness is binary: 98% means broken. The gates — a 24-case
enforcement matrix (100% required), the injection corpus (recall ≥ 90%,
zero false positives), seed-deterministic fuzz invariants across two
independent gateways, tamper-evident audit scenarios, and overhead measured
against an ungoverned direct call. `--json` emits an environment-stamped,
regression-comparable report; CI runs the benchmark as a release gate.
Design rationale, methodology, baseline numbers and honest limits:
**[docs/tollgate-bench.md](docs/tollgate-bench.md)**.

## MCP server

```bash
python -m tollgate mcp          # stdio JSON-RPC 2.0, zero dependencies
```

Point any MCP client (Claude Desktop, Cursor, your own agent) at it — every
tool call crosses the full enforcement chain. Policy denials come back as
`isError` tool results with reasons, so the calling model can adapt.

### MCP upstream proxy — govern *any* MCP server

Tollgate is also an MCP **client**: point it at any third-party MCP server
and it spawns the upstream, pulls `tools/list`, and registers every tool
under a namespaced prefix (`upstream__tool`) — each call then crosses the
full enforcement chain, and upstream tools follow the same policy rules as
local ones:

```yaml
mcp_upstreams:
  - name: github
    command: ["npx", "-y", "@modelcontextprotocol/server-github"]
    allow_tools: ["get_*", "list_*"]
    risk: read
```

(A bundled demo upstream ships as `python -m tollgate.mcp_demo_upstream`;
see the `mcp_upstreams` section in `policies/demo.yaml`. A runnable real-world
example — a zero-dependency filesystem MCP server at `examples/fs_server.py`,
wired read-only allow / write deny — is configured there too: `fs_write_file`
is rejected fail-closed and never touches the disk.)

To use Tollgate as the governance hub for Claude Desktop (or any MCP
client), see **[docs/claude-desktop.md](docs/claude-desktop.md)** — one
config entry gives every tool call (yours *and* every upstream's) the
full enforcement chain, with the audit hash chain as the receipt.

## Install

Python ≥ 3.10, **zero mandatory dependencies** (a bundled YAML-subset parser
is used unless PyYAML is installed):

```bash
pip install tollgate-gateway # PyPI (import / CLI name stays `tollgate`)
pip install -e .             # or from this repository
tollgate demo                # or: python -m tollgate demo
```

## CLI surface

| Command | Purpose |
|---|---|
| `demo` / `demo-web` | scripted adversarial scenario (terminal / web approvals) |
| `serve` | approvals console + audit replay UI |
| `transfers`, `freeze`, `recover`, `release` | settlement ledger operations (authenticated) |
| `verify` / `verify-approval` | hash-chain check / approval signature check |
| `trace`, `reconcile` | attribution timeline / cross-ledger reconciliation |
| `explain`, `compliance` | decision rationale / compliance report |
| `budgets`, `usage` | budget pools / token & latency metering |
| `golden`, `redteam`, `drill` | drift regression / adversarial suite / attack replay |
| `bench` | TollgateBench — five-dimension governance benchmark (binary gates + JSON report) |
| `agent` | live agent against any OpenAI-compatible endpoint |
| `onboard` | risk-grade a new tool, draft policy YAML |
| `seal`, `keygen` | tool fingerprint baseline / Ed25519 keypairs |

## Docs

- [威胁模型 / Threat model](THREAT_MODEL.md) — trust boundaries, STRIDE mapping, residual risks
- [TollgateBench / 基准研究](docs/tollgate-bench.md) — dimensions, methodology, baseline numbers
- [中文文档](README.zh-CN.md)

## Roadmap

- Ed25519 for terminal approvals & settlement ops (web approvals done)
- Pluggable storage (Postgres) for multi-instance deployments
- Delegation chains (agent acting on behalf of a department)
- Policy-change approval workflow (policy as a first-class audited asset)

## Contributing & security

See [CONTRIBUTING.md](CONTRIBUTING.md). Security issues: follow
[SECURITY.md](SECURITY.md) — please do not open public issues for
vulnerabilities.

## License

[Apache-2.0](LICENSE)
