Files
patchpass/README.md
T
Space-Banane 7e05dd918c
Deploy / Build (push) Successful in 28s
Deploy / Test & Lint (push) Failing after 29s
Deploy / Build and Push Docker Image (push) Has been skipped
Patchpass V1
2026-07-18 20:14:44 +02:00

151 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PatchPass
**A human approval layer for AI agents.**
> Review changes. Approve intent. Let agents proceed.
Agents submit structured change requests containing code diffs, configuration updates, or custom values. Humans review and approve them in the browser, then agents verify the platform-signed decision through the API before applying anything.
---
## How it works
```
Agent PatchPass Human
│ create_request ───────────► │ │
│ (diffs/config/custom) │ normalize · hash · store │
│ ◄─── request_id + URL ────────│ ──── notify (WS) ──────────► │ reviews in browser
│ │ │ APPROVE / REJECT / REQUEST_CHANGES
│ get_request ──────────────► │ ◄──── signed decision ──────│
│ ◄─── state + receipt ─────────│ │
│ consume_approval ─────────► │ mark CONSUMED (single-use) │
│ ◄─── receipt (HMAC) ──────────│ │
│ apply changes │ │
```
- **Decisions are platform-signed.** Approvals and rejections carry an HMAC-SHA256 receipt bound to the exact reviewed content (`content_hash`). If the agent changes anything after approval, the receipt no longer matches.
- **Approvals are single-use.** An agent must `consume` an approval before proceeding; it cannot be replayed.
- **Two ways in for agents:** a REST API (`/v1/...`) and an MCP server (`/mcp`), both authenticated with a per-agent API key and backed by the same service layer.
## Request states
`PENDING` · `CHANGES_REQUESTED` · `APPROVED` · `REJECTED` · `EXPIRED` · `CONSUMED` · `CANCELLED`
No update is possible after approval, rejection, expiry, consumption, or cancellation. A `REQUEST_CHANGES` decision requires a comment and returns the request to the agent, which can `update_request` to resubmit (highlighted in the UI as **UPDATED**).
## Limits
| Limit | Value |
|---|---|
| Requests per agent per hour | 15 |
| Agents per human | 5 |
| Simultaneous pending requests per agent | 110 (human-configured, default 5) |
| Request expiry | default 30 min, max 12 h |
## Tech stack
| Layer | Technology |
|---|---|
| Backend | Node.js + TypeScript, [rjweb-server](https://server.rjweb.dev) |
| ORM | Prisma 7 (`@prisma/adapter-pg`) |
| Database | PostgreSQL |
| Frontend | React + TypeScript + Tailwind CSS (Vite), served by the backend |
| Realtime | rjweb WebSocket channels |
| Tests | Vitest |
## Repository layout
```
Backend/ Node + TypeScript API (rjweb-server) + Prisma
src/
index.ts server bootstrap + static UI serving
lib/ service layer, auth, signing, limits, crons, MCP tools
routes/ REST (/api, /v1), MCP (/mcp), WebSocket (/api/ws)
tests/ Vitest integration tests
prisma/schema.prisma
UI/ React + Tailwind frontend (builds to UI/build)
Dockerfile multi-stage build (UI + backend)
docker-compose.yml backend + postgres
.gitea/workflows/ CI: build · lint · test · push image
```
## Running locally
Prerequisites: Node 24+, pnpm, and Postgres (or Docker).
```bash
# 1. Start Postgres (Docker)
docker run -d --name patchpass-db \
-e POSTGRES_USER=patchpass -e POSTGRES_PASSWORD=patchpass -e POSTGRES_DB=patchpass \
-p 5433:5432 postgres:16-alpine
# 2. Backend
cd Backend
cp ../example.env .env # then edit DATABASE_URL / INSTANCE_SECRET
pnpm install
pnpm generate
pnpm migrate # apply migrations
pnpm dev # http://localhost:5000
# 3. UI (separate terminal, for hot-reload dev)
cd UI
pnpm install
pnpm dev # http://localhost:3000 (proxies /api to :5000)
```
For a production-style run, `cd UI && pnpm build` — the backend then serves `UI/build` at `/`.
### Tests
```bash
cd Backend
pnpm test # spins up against the test database (see vitest.config.ts)
```
## Deploying
```bash
cp example.env .env # set DATABASE_URL=...@db:5432/..., a strong INSTANCE_SECRET
docker compose up -d --build
```
The backend applies migrations on boot and serves the UI. The first account to register becomes the **admin**.
## Connecting an agent
Create an agent in the UI, then use its API key.
**OpenClaw** — add to `~/.openclaw/openclaw.json`:
```json
{
"mcp": {
"servers": {
"patchpass": {
"transport": "streamable-http",
"url": "https://your-host/mcp",
"headers": { "x-api-key": "pp_agent_..." }
}
}
}
}
```
**REST**:
```bash
curl -X POST https://your-host/v1/change-requests \
-H "x-api-key: pp_agent_..." -H "Content-Type: application/json" \
-d '{"title":"Bump timeout","changes":[{"type":"config","path":"timeout","before":30,"after":60,"content_type":"integer"}]}'
```
Tell your agent: *before taking any consequential action, call `create_request`, wait for approval, then `consume_approval` before proceeding.*
## Privacy & data
Humans can export all their data as JSON and delete their account (cascading to agents, requests, and notifications) from **Settings**. Agent icon URLs are fetched once for validation and never stored. See the in-app Privacy Policy and Terms of Service.
## License
MIT-0