Space-Banane b47077d0cb
Deploy / Build (push) Successful in 28s
Deploy / Test & Lint (push) Failing after 29s
Deploy / Build and Push Docker Image (push) Has been skipped
fix: update TEST_DATABASE_URL to use service name for Docker
2026-07-18 20:23:51 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00
2026-07-18 20:14:44 +02:00

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
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).

# 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

cd Backend
pnpm test        # spins up against the test database (see vitest.config.ts)

Deploying

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:

{
  "mcp": {
    "servers": {
      "patchpass": {
        "transport": "streamable-http",
        "url": "https://your-host/mcp",
        "headers": { "x-api-key": "pp_agent_..." }
      }
    }
  }
}

REST:

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

S
Description
No description provided
Readme 374 KiB
Languages
TypeScript 96.7%
CSS 2.4%
Dockerfile 0.5%
HTML 0.4%