Security Model

Version 1.2.0

This page describes exactly what's enforced today, and where the real, current limits are — precisely, not rounded up.

Content can't execute anything

Every entry is restricted to a small, explicit allowlist of HTML — checked at write time and again at render time, so nothing that reaches the repository through any path can skip validation. Scripts, inline event handlers, and iframes from arbitrary sources are rejected outright, regardless of how they're written or what wrote them. This is enforced by the sanitizer itself, not by a rule an agent is asked to follow.

Who can write

Access to write tools is derived live from real GitHub collaborator permissions on the content repository, checked fresh on every connection — not from a separate account system. A signed-in identity with no real access to the repository gets no tools at all, not a token that happens to unlock nothing.

Current, honest scope: only someone with real write access to the private content repository can reach the write path. That's a genuine guarantee today. A further hardening tier — GitHub App-based branch protection that excludes even the repository owner's own personal credentials from pushing directly — is real and buildable, but not yet the default, partly because the underlying platform mechanism isn't available on every GitHub plan for private repositories. Don't treat that stronger claim as true until it's explicitly documented as shipped.

While the server's authentication is set to permissive pass-through (the default for local, solo use), never expose it beyond localhost or a private network. Anyone who can reach the endpoint can call every write tool.

Roles

Two roles exist today, both derived from the same GitHub permission check: a Writer can create, edit, and publish content; a Designer can do everything a Writer can, plus edit site-wide style tokens. Designer is a superset of Writer, not a separate, equally-restricted tier — it mirrors how GitHub's own permission levels already nest.

Every mistake is recoverable

Because storage is git, nothing is ever actually destroyed. A deleted entry can be restored by reading its content back out of git's own history. A bad publish can be undone through a real, reviewable change rather than a silent overwrite. Two independent layers, either one usable without touching the other: content-level rollback, and instant deploy-level rollback to any previous build.