kPlan
Approval gateway for agent-written plans - agents submit markdown, humans review a real page, the answer goes back signed.
The problem
Coding agents produce plans faster than anyone can responsibly approve them. The failure mode is predictable: the plan scrolls by in a terminal (at 3x speed), the human types "looks good", and nobody can later say which version of what was approved.
kPlan makes the approval a first-class artifact. An agent publishes markdown through an API (or a bundled MCP server (a service that exposes tools to coding agents)), gets a shareable URL back, and waits. A human reads a server-rendered page, comments on individual headings, and approves or rejects a specific version. The decision travels back to the waiting process as an HMAC-signed webhook (a keyed hash that authenticates a message), a long-poll (client holds an open request until the server has a result) response, or an SSE event (a one-way HTTP event stream).
kPlan is API-first for agents and web-first for humans.
Architecture
kPlan is a single Bun/Hono application with a React 19 client, persisting to SQLite in WAL mode (write-ahead logging: changes append to a log before the main file). Markdown stays the source of truth: content is rendered and sanitized once at write time, and the sanitized result is stored with the immutable version. The pipeline is markdown-it with task lists, footnotes, GitHub alerts and containers, Shiki dual-theme highlighting, KaTeX, and client-rendered Mermaid - all bundled, so production needs no runtime CDN.
Versioning is the load-bearing part. Updating a plan creates a new immutable
version under the same URL and resets approval to review. Decisions are
version-bound: a decision against a stale version returns 409, repeating the
same decision on the same version is idempotent (safe to repeat without changing the result), and old versions stay
readable as snapshots with diffs between them. Review events are ordered and
idempotent on (plan, version, cursor), so an agent can consume them over
webhooks (at-least-once, with retry cycles and an operator CLI for exhausted
deliveries), long polling, or SSE without double-processing.
Tokens are scoped (plans:read, plans:write, plans:decide) and stored
only as SHA-256 hashes. Self-provisioned tokens deliberately cannot decide
and are sandboxed to the plans they created - an agent can mint its own
credentials, but approval authority stays with the operator.
Boundaries
An approval in kPlan is a controlled signal, nothing more. kPlan never executes agent work, never mutates repositories, and never turns "approved" into "run". The agent still does the work under its own constraints; kPlan makes sure a human said yes, to a specific version, on the record (where it belongs).
kPlan treats rendering agent-generated content as hostile: embedded HTML is disabled before a second server-side sanitization pass, Mermaid runs in strict mode with its SVG sanitized again, and production ships a nonce-based CSP (browser rules that restrict which scripts and origins a page may load) with no external origins. Browser actions are stateless signed tokens bound to plan, version, and action; webhook destinations are deny-by-default against an exact host allowlist; plan bodies, uploads, and every API surface have size and rate limits. It deploys as one process - or one compiled binary - behind a reverse proxy (a server that receives requests and forwards them to internal services), and is intentionally single-instance.