hbar-systems/permitd

GitHub: hbar-systems/permitd

permitd 是一个零依赖的 Python 库,为 AI agent 循环提供人在环中的工具执行治理,通过提议-批准-执行-审计流程确保敏感操作获得人工授权。

Stars: 0 | Forks: 0

# permitd **用于 agent 循环的受治理工具执行。** ![agent 提议一个受限调用,人类在另一个终端批准它,调用执行,并且审计记录生成](https://static.pigsec.cn/wp-content/uploads/repos/cas/71/719ca64c969a89a0f49209af95b78802c9a29e48442389dfe570c79c204779bd.gif) 你的 agent 循环想发送电子邮件、写入文件、访问 API。而你想 在其中加入人类的决策——一种 agent 无法伪造、重放或篡改 为不同参数的决策——并且无论结果如何,都会在审计日志中留下记录。 ``` propose(tool, args) ──> permit (signed, TTL, single-use) ──> approve (a human, out-of-band: CLI, or any callable) ──> execute (verify + burn, atomically) ──> one audit line lands (append-only JSONL) ``` permitd 就是实现这一流程的轻量级、仅依赖标准库的 Python 库。它也是 **循环状态**:许可保存在 SQLite 中,因此在 agent 循环第 N 轮提议的调用 可以从另一个终端批准,并在第 N+K 轮执行—— 跨越重启,跨越进程。 除执行外的任何结果都会默认失败。缺失、过期、被拒绝、 被篡改、参数不匹配或已使用的许可都会被拒绝,并且 拒绝记录也会被审计。 ## 安装 ``` pip install permitd ``` Python ≥ 3.10,零依赖。 ## 六十秒,两个终端 **终端 1 — agent 端** (`agent.py`): ``` import time from permitd import Gate, RED gate = Gate(db="permitd.db") @gate.tool(tier=RED, description="send a message to someone") def send_message(to, body): return f"delivered to {to}: {body!r}" args = {"to": "alice", "body": "hello from the loop"} r = gate.call("send_message", args) print(r.error) # "... permit PRM-xxxx is proposed ..." pid = r.permit["id"] while gate.get(pid).status == "proposed": # this state survives restarts time.sleep(1) r = gate.call("send_message", args, permit_id=pid) print(r.result if r.ok else r.error) ``` ``` python agent.py ``` **终端 2 — 人类端:** ``` $ permitd pending 1 pending permit(s): PRM-3f9c21ab44de [proposed] send_message args: {"to": "alice", "body": "hello from the loop"} proposed: 2026-07-29T18:12:03+00:00 ttl: 300s $ permitd approve PRM-3f9c21ab44de approved — PRM-3f9c21ab44de is executable for 300s, single use, bound to exactly these arguments ``` 终端 1 唤醒并打印 `delivered to alice: 'hello from the loop'`。 轨迹如下: ``` $ permitd audit {"ts": "...", "event": "proposed", "permit_id": "PRM-3f9c21ab44de", "tool": "send_message", ...} {"ts": "...", "event": "approved", "permit_id": "PRM-3f9c21ab44de", ...} {"ts": "...", "event": "executed", "permit_id": "PRM-3f9c21ab44de", "ok": true} ``` 这就是整个产品:提议、批准、执行、审计记录。 ## 许可实际保证的内容 - **绑定到精确参数。** 许可的范围限定于 `sha256(tool + canonical_json(args))`。对“向 Alice 发送 X”的批准无法 重放为“向 Eve 发送 Y”——键的顺序和空格不会改变绑定; 任何值的改变都会导致失败 (`args_mismatch`)。 - **单次使用,原子操作。** 消耗许可是一次 SQLite 的比较并交换操作 (`UPDATE ... WHERE status='approved'`),因此两个进程竞争同一个 许可不可能同时成功 (`already_used`)。 - **双重时间限制。** 提议可以在 `ttl_seconds`(默认为 300)内被批准;生成的批准可以在另一个 `ttl_seconds` 内执行。无法解析的 时间戳将被视为过期。 - **HMAC 签名。** 批准会生成 `HMAC-SHA256(secret, id.binding_hash.approved_at)`,在执行时 重新验证——在内核背后被篡改的存储行将会失败 (`bad_signature`)。 - **处处默认失败。** 任何内核无法明确验证的内容—— 包括“甚至无法检查参数”——都是拒绝,而不是 放行。拒绝行为及其原因都会被审计。 ## 层级 `Gate` 是一个在内核之上具有三个层级的小型注册表: | 层级 | 含义 | 门控 | |---|---|---| | `GREEN` | 对自身状态的只读 | 自由运行,接受审计 | | `YELLOW` | 外部读取(搜索、获取) | 一个常驻开关:`gate.standing_authorization = True` | | `RED` | 写入 / 执行 / 发送 | 每次调用的许可:如上所述的流程 | 如果你不需要注册表,请直接使用内核: ``` from permitd import PermitKernel, SqliteStore, AuditLog kernel = PermitKernel(SqliteStore("permitd.db"), secret_path="permitd.db.secret", audit=AuditLog("permitd_audit.jsonl")) p = kernel.propose("deploy", {"target": "prod"}) kernel.approve(p.id) # or from the CLI / your own UI kernel.execute("deploy", {"target": "prod"}, p.id, runner=do_deploy) ``` `approve` 只是支持存储的内核上的一个方法——从 CLI、Slack 处理程序、 HTTP 端点或人类所在的任何地方调用它。 ## 出站防护 在任何非 GREEN 调用运行之前——**包括在提议时**——它的参数将 被扫描是否包含凭证特征内容:私钥块、`Bearer`/`Basic` 标头、AWS/GitHub/Slack/Stripe/OpenAI/Anthropic/Google 密钥特征、内联 `api_key=...` 赋值、此进程自身敏感环境 变量的值,以及保守的高熵后备方案。将机密引导 至工具参数的中毒上下文会在任何内容 离开之前,在显示任何批准卡片之前被拒绝,并且拒绝原因会标明 匹配的*特征*,而不是值本身。 ## MCP:对任何 agent 的工具进行门控,包括 Claude Code [`examples/mcp_server/`](examples/mcp_server/) 是一个 MCP 服务器,其工具会 经过门控。将任何使用 MCP 通信的 agent 指向它,该 agent 将获得 提议 → 批准 → 执行 + 审计,且**无需对 agent 端进行任何更改**: agent 调用 RED 工具,被告知“许可 PRM-… 已提议,等待批准”, 你在另一个终端运行 `permitd approve PRM-…`,agent 重试并且 调用执行。无论结果如何,审计记录都会生成。 ## 存储 `SqliteStore`(默认,持久化,原子化消耗)和 `MemoryStore`(测试, 临时)开箱即用。其他任何实现都需要五个方法——请参阅 [`store.py`](src/permitd/store.py) 中的 `PermitStore` 协议;保持 `burn` 是比较并交换操作,否则你将失去单次执行的保证。审计跟踪是 一个独立的、仅追加的 JSONL 文件,因此可以保持使用 `tail -f` 进行追踪。 ## permitd 不是什么 不是 agent,不是框架,不是内存,不是 RAG。它对你的循环、 你的模型或你的 prompt 没有任何意见。它是跨轮次保持“可以运行这个吗?” 状态的层——以及运行完成后的凭证。 ## 源流 从 [brainfoundry-nous](https://github.com/hbar-systems/brainfoundry-nous) 的工具治理内核中提取, 在那里它运行在生产环境中,对个人 AI 节点的工具进行门控。 提议/确认/执行 + 审计的语法可以追溯到 [hbar.brain.console](https://github.com/hbar-systems/hbar.brain.console) (2026-03)。设计说明:[DESIGN.md](DESIGN.md)。 ## 许可证 MIT。
标签:Python, SOC Prime, 人机交互, 审计日志, 开发工具, 无后门, 时序数据库, 权限控制, 逆向工具