Adaptive publishing infrastructure for the sovereign web.
SQLite-first, zero-trust, zero telemetry. Policy-governed runtime with adaptive system modes, sandboxed plugins, transactional event outbox, durable audit trail, and fault-tolerant federated publishing.
Complete digital sovereignty in one binary.Own your content. Own your communication. Own your infrastructure.
Publishing is the core identity, VayuMail the native sovereignty layer, VayuPGP the native privacy layer, and VayuOS the native control layer — all in a single Go binary, single process, single config.
Deeper analytics and a more complete mailbox — all still in one binary, privacy-first.
VayuAnalytics — reporting periods up to 3 years. Pick any window from 24h
to 3 years; it flows through every card, goals/journey, and exports.
VayuAnalytics — conversion goals. Track a page view or custom event as a
goal and see completions and conversion rate.
VayuAnalytics — visitor journey. Most common page-to-page paths with
(entry)/(exit) markers.
VayuAnalytics — export. Download any report as CSV or JSON (computed
locally, no PII).
VayuAnalytics — country/region/city. Read server-side from your reverse
proxy (e.g. Cloudflare CF-IPCountry/CF-IPCity, X-Geo-*). VayuPress does
no GeoIP lookup, bundles no GeoIP database, and never stores an IP — geo
shows only when your proxy supplies it.
VayuAnalytics — live panel. Active visitors and pages, refreshed every 10s.
VayuMail — junk filter, account password/disable, reply & forward. A
fully-local spam heuristic files junk on inbound; set or disable mailbox
passwords from the panel; reply/forward pre-filled from the original message.
"Stable Private Email" — the inbound half of VayuMail. v1.9.0 completes the
receive side so VayuPress is a mailbox you can actually receive and read mail in,
still inside one binary.
SMTP-receive server — a pure-Go RFC 5321 listener (EHLO/MAIL/RCPT/DATA/
RSET/NOOP/QUIT) that accepts mail only for your local domain (no open relay),
undoes dot-stuffing, and enforces size caps, delivering into Maildir.
IMAP read server — a pure-Go RFC 3501 subset (CAPABILITY, LOGIN via your
VayuPress account, LIST, SELECT, FETCH incl. BODY[]/FLAGS/SIZE/INTERNALDATE,
STORE \Seen, LOGOUT) so standard clients (Thunderbird, mobile) read the
Maildir.
Transparent PGP decryption on read — when VayuPGP holds the account's key,
IMAP serves the decrypted message body; best-effort, and it never blocks
delivery.
Opt-in by design — the inbound listeners start only with
VAYUOS_MAIL_INBOUND=on (Operational Simplicity Doctrine); when off, no mail
port is opened and the binary boots unchanged.
Scope: inbound SPF/DKIM/DMARC verification, greylisting, and IMAPS/TLS
hardening are tracked as the next milestones in docs/ROADMAP-v1.9.md.
Sovereignty release — VayuAnalytics, VayuOS Phase 2 (VayuMail + VayuPGP), and the Theme Studio Gallery.
VayuAnalytics — privacy-first, cookieless, no-PII web analytics. Pageviews,
sessions, top pages, referrers, UTM campaigns, custom events, funnels,
retention cohorts and revenue — stored locally in SQLite. Visitor identity is
a server-side daily-rotating salted hash: no cookies, no localStorage,
no IP or User-Agent ever stored, no consent banner required, nothing to leak
on a database compromise. The public ingest endpoint is body-capped and
per-IP rate-limited; a retention sweeper enforces data minimisation.
VayuPGP — native end-to-end PGP privacy layer (built on ProtonMail
go-crypto). Ed25519 + Curve25519 keypairs auto-generated on account creation,
private keys AES-256-GCM encrypted at rest under a key derived from the
master secret (never logged, never leave the server), full
encrypt/decrypt/sign/verify, key rotation that preserves old messages, and a
Web Key Directory (WKD) served at /.well-known/openpgpkey/ so any GPG
client can discover your keys.
VayuMail — native outbound mail sovereignty layer. RFC 6376 DKIM
signing (relaxed/relaxed, RSA-SHA256), direct-to-MX delivery with
opportunistic STARTTLS (no third-party relay), a durable SQLite retry queue,
Maildir storage, automatic MX / SPF / DKIM / DMARC record generation with
live DNS health checks, and automatic PGP encryption of outgoing mail when
a recipient key is discoverable. Mail never leaves your server unencrypted to
a third party.
VayuOS control layer — a typed event bus (account creation auto-provisions
a PGP keypair + mailbox), an ordered boot orchestrator with graceful
degradation, and a health monitor, all surfaced in the /os/vayuos console
(keys, mail queue, DNS health, security updates).
Security-update watcher — an opt-in (privacy-default-off) advisory that
tracks upstream security releases of the crypto dependencies powering VayuPGP
and VayuMail, surfacing available patches in the panel. It transmits nothing
about your site.
Theme Studio Gallery — expanded preset gallery (20+ themes incl. the new
Gale editorial and Zephyr bright-creative layouts) with a CSP-safe
Pico bridge so presets restyle the public site instantly, plus WCAG-AA
contrast and ≥44px touch targets.
Scope note: VayuMail v1.8.0 delivers the outbound sovereignty path
(submission, DKIM, queue, DNS, WKD, PGP). A full inbound MX + IMAP server is a
governed future milestone under the Operational Simplicity Doctrine.
VayuOS — unified operator powerhouse, draft/publish workflow, and member signup.
Draft/publish workflow — articles are published or draft. The VayuOS
post manager (/os/posts) lists every post with a live status pill and
one-click Publish / Unpublish that purges render caches immediately.
All operator tools inside VayuOS — System Modes, Policy Engine, Runtime
Topology, Replay Explorer, Fault Manager, and ADR Registry now render inside
the VayuOS chrome. Old /admin/* operator URLs 301-redirect.
Member signup page (/signup) — branded reader-facing page wired to the
magic-link auth flow.
Ghost-style homepage auth buttons — optional Sign in / Sign up buttons in
the public nav, toggled per-site from VayuOS → Members settings.
Three draft-content security fixes — API, render cache, and comment API
all now treat drafts as non-existent to anonymous callers (see Security below).
Security (v1.7.0)
ID
Severity
Surface
Fix
LEAK-1
Critical
GET /api/v1/articles/{slug}
Returns 404 for drafts to unauthenticated callers
LEAK-2
High
On-disk render cache
Worker verifies DB status before caching draft HTML
LEAK-3
Low
Comment API
Rejects requests whose slug resolves to a draft
Upgrading from v1.6.0
Run migrations — migration 030 adds the status column to articles.
All existing rows default to published; nothing is hidden after upgrade.
The VayuOS shell at /os is unchanged; old operator-page URLs 301-redirect.
One admin, for real — Admin v2 removed (ADR-0069 Stage 3). VayuOS at /os is
now the only admin, and the block editor owns every authoring flow.
Native create path — brand-new posts open the /os block editor and are
created on first Save through the authoritative article service (no more
delegating to the v2 editor).
Native legacy-post editing — opening an existing legacy (non-block) post
loads it in the block editor, pre-seeded with an in-memory import of its HTML;
the import is not persisted and the published content is untouched until Save.
Admin v2 deleted — admin_ui.go, the v2 login handlers, admin-v2.css,
admin-v2.js and the v2 e2e specs are gone, along with the ADMIN_LEGACY
escape hatch and deprecation banner.
Permanent (301) redirects — /admin, /admin/v2[/...] and
/admin/v3[/...] now 301-redirect into the /os equivalent.
Upgrading from v1.5.0
No data migration. The admin is at /os; old /admin, /admin/v2 and
/admin/v3 URLs redirect there automatically. Update any bookmarks/automation
that hard-coded /admin/v2, and drop the ADMIN_LEGACY env var (now a no-op).
VayuOS — One Admin (ADR-0069, ADR-0073) — the three historical admin
surfaces (the classic console /admin, Admin v2 /admin/v2, and Admin v3
/admin/v3) consolidate into a single, fast admin: VayuOS, mounted at /os.
All three legacy paths now 302-redirect into the /os equivalent. The block
editor gains depth, the Theme Studio becomes native, and legacy posts can be
adopted into blocks losslessly — all on the same sovereign single binary with
zero CDNs and a strict CSP (no unsafe-eval, no unsafe-inline, per-request
nonces).
AI-assist slash commands (opt-in) — when VAYU_AI_URL is configured, the
block editor's slash palette gains an AI section (continue, rewrite, summarise)
with an inline Accept/Discard overlay. Disabled and invisible by default;
nothing leaves your server unless you wire up a local model.
Inline version-history diff — a History panel lists recent versions and
renders a word-level LCS diff against the working draft.
Native Theme Studio in VayuOS — preset gallery + design-token editor with
a CSP-clean live preview via scripted CSSOM custom-property writes (no <style>
injection), served from session-gated /os/api/theme/* mirrors.
Convert-to-blocks (ADR-0073) — an explicit, confirmed, non-destructive
action imports a legacy article's HTML into a block document (blocks_json
side-car) via blockrender.ImportHTML. articles.content is never touched, so
the action is reversible by simply not saving.
Governance panel (/os/governance) — a dedicated control surface for the
adaptive-governance runtime: current system mode + full transition lineage, the
severity-classified error-budget ledger, and a live policy-engine evaluation
(pass / warning / fail). Server-rendered, CSP-clean.
Formal plugin interface spec (ADR-0074) — docs/plugins/SPEC.md is a
normative, RFC-2119, independently versioned (v1.0) contract: plugin kinds,
manifest schema, deny-by-default capability model, line-oriented JSON IPC
protocol, hook events, lifecycle and conformance. The Tools panel gains a live
registry of sandboxed out-of-process plugins (running/quarantined, PID,
invocations, crashes).
Legacy-route log warnings — every hit on /admin, /admin/v2 or
/admin/v3 emits a structured warn log line naming the /os target and the
removal release, so operators can find stale bookmarks and integrations.
Legacy admin surfaces redirect to VayuOS (ADR-0069) — /admin,
/admin/v2[/...] and /admin/v3[/...] now 302-redirect to the /os
equivalent. Set ADMIN_LEGACY=1 to keep the deprecated v2 pages reachable for
one more release; they are scheduled for removal in v1.6.0.
Upgrading from v1.4.0
No breaking changes. The admin now lives at /os; bookmark it there. Old
/admin, /admin/v2 and /admin/v3 URLs redirect automatically. Operators who
still rely on the deprecated v2 pages must set ADMIN_LEGACY=1. AI-assist stays
off unless VAYU_AI_URL is set.
Sovereign Rich Media & Theme Studio (ADR-0070) — put diagrams, video, and
arbitrary embeds into posts, and restyle the whole site from a visual editor,
without a single third-party reader-side request. Every capability is a typed
block or server-rendered asset; the strict reader CSP (no unsafe-eval, no
unsafe-inline, no wildcard frame-src/img-src) is never relaxed by default.
Pure-Go Mermaid → SVG diagrams — diagram blocks compile six grammars
(flowchart, sequence, pie, state, class, gantt) to static, themeable, sanitised
SVG entirely on the server. No headless browser, no Node, no client
JavaScript, no eval. Unsupported sources degrade to an annotated code block.
Live editor preview via a debounced endpoint; results cached in diagram_cache.
Privacy-first embeds — paste any URL for a self-hosted link card
(OpenGraph fetched via the SSRF-hardened safefetch client; thumbnail
imported, never hotlinked). YouTube/Vimeo become click-to-load facades:
nothing third-party loads until the reader clicks, then a sandboxed iframe opens
to the cookie-free origin. A per-page CSP builder narrows frame-src to a
closed allowlist only for pages that need it.
Theme Studio — a sovereign design-token system: typed tokens (colour ramps,
typography, spacing, radii), a hex-validated CSS-variable compiler, eight
system-font presets (Aurora, Slate, Terminal, Sepia, Carbon, Ocean, Sakura,
Default), and a Studio tab with a preset gallery + live preview that
re-themes instantly via CSSOM — no inline styles, CSP stays strict.
Security — anchored video-host matching (refuses spoofed
evil.com/youtube.com/… URLs), a fail-fast pre-flight SSRF host barrier in
safefetch, and all emitted HTML/SVG through bluemonday allowlists.
Upgrading from v1.3.0
No breaking changes. Start the server once and migrations 027–029 apply
automatically (embed cache, diagram cache, theme tokens). No configuration
changes; rich media and the Theme Studio are available immediately.
VayuOS — a ground-up admin & block editor that surpasses Ghost, WordPress,
and Substack in design, depth, and security, while remaining a sovereign single
binary with zero CDN dependencies and a strict CSP (no unsafe-eval, no
unsafe-inline). Mounted at /os alongside /admin/v2 — fully
non-breaking (ADR-0068).
Design system — hand-authored CSS, CSS-custom-property theming (dark/light/auto),
grouped sidebar, command palette (⌘K), mobile bottom-nav, toast notifications.
Block editor — typed-block document stored as JSON, rendered server-side
through HTML escape + bluemonday UGC sanitisation (internal/blockrender).
No raw-HTML escape hatch. Slash-command palette, autosave (⌘S), and a
DOMPurify-guarded live preview. Legacy posts stay in the lossless v2 editor.
Two-factor auth (TOTP) — RFC 6238 in pure Go stdlib (internal/totp,
validated against RFC test vectors). Two-step enrolment: secret stored disabled
until verified, so abandoned setup can never lock an operator out. Enforced on
both v2 and v3 sign-in surfaces.
Intelligence — native SEO readiness dashboard and privacy-preserving
analytics page sourced entirely from the local SQLite database.
Security hardening — CodeQL-clean: html.EscapeString called directly
(not via a function alias) in all block-editor render paths; email Subject now
emitted as an RFC 2047 base64 encoded-word (mime.BEncoding), clearing both
the go/reflected-xss and go/email-injection findings.
Upgrading from v1.2.0
No breaking changes. Start the server once and migrations 025–026 apply
automatically (adds blocks_json to articles and totp_secret/totp_enabled
to users). Admin v2 is unaffected; Admin v3 lives at a separate path.
Four shipped tiers of new capability — all single-binary, all sovereign, all
honouring the strict-CSP and governed-write invariants.
Tier 1 — Sovereign foundations: standard-library SMTP email + double-opt-in
newsletter, durable scheduled publishing, multi-author accounts (Argon2id +
server-side sessions), and stdlib-only automatic image optimization (no CGO).
Tier 2 — Reach & insight: cookieless zero-PII analytics, HMAC-signed outbound
webhooks with retry + delivery audit, Mastodon auto-posting, Ghost/WordPress
importers, a local-Ollama AI writing assistant (suggest-only), and
memberships & paywalls with passwordless magic-link sign-in and an optional,
signature-verified Stripe webhook.
Tier 3 — Reading polish (ADR-0066): server-side syntax highlighting
(chroma, style-src 'self'-safe via a highlight-before-sanitise placeholder
pipeline), related articles (precise comma-token tag matching), reading-time,
PDF/document uploads, comment-approval emails, and an installable PWA with
offline service worker.
Tier 4 — Enterprise interfaces (ADR-0067): a read-only GraphQL content
API (query-only — no mutation surface), internationalisation with
Accept-Language negotiation and operator-editable catalogs, customisable
transactional email templates, and a real-time SSE event stream. Cloudflare
edge-purge + IndexNow CDN push fire on every mutation.
Upgrading from v1.1.0
No breaking changes. Start the server once and migrations 019–024 apply
automatically. Every new capability is opt-in and a safe no-op until configured
(SMTP, Stripe, Mastodon, Ollama, Cloudflare, etc.).
Built-in vayupress migrate command — import Markdown folders straight
into the database (migrate markdown, migrate list, migrate info); no
separate tool to build. Idempotent (INSERT OR IGNORE), YAML-frontmatter
aware, with --dry-run.
Multi-format post editor — author each post in Markdown or raw HTML
via a segmented toggle. The chosen format and editable source round-trip
losslessly through the new article_sources side-car table (migration 018);
the public renderer always receives server-sanitised HTML.
Dual-write autosave — every save persists the editable source and the
rendered HTML in parallel; new posts create-and-redirect to a permanent URL.
Security hardening — HTML-escaped article title/slug in the admin
dashboard, XML-escaped sitemap <loc> slugs, and CDATA-injection defence in
the RSS feed (security review 2026-06-19).
Upgrading from v1.0.0
No breaking changes. Start the server once and migration 018 applies
automatically. The legacy /admin console is untouched. Existing posts open in
the editor in HTML mode until first saved in Markdown mode.
Platform Screenshots
Screenshots are regenerated automatically from a live instance by the
screenshots CI workflow and committed
back to docs/screenshots/. Run it via GitHub → Actions → screenshots → Run workflow.
Public Homepage
Public homepage — article grid with tag filtering, dark/light mode toggle, zero-telemetry footer, system mode indicator. Styled on vendored Pico CSS served locally to keep the strict style-src 'self' CSP intact.
Article Page
Rendered article — JSON-LD schema, author/date meta, tag strip, reading time, zero third-party requests.
Theme Studio — Native to VayuOS
The Theme Studio, now native to VayuOS (/os/theme) — a preset gallery
and design-token editor with an instant live preview. Colour ramps, typography
and spacing compile to a single sovereign stylesheet served from your own origin.
The preview applies values through CSSOM setProperty, so it stays inside the
strict style-src 'self' CSP — no inline styles, no third-party fonts, no CDNs
(ADR-0070, ADR-0069).
VayuOS — The Single Control Panel & Block Editor
The VayuOS dashboard (/os) — grouped sidebar, stat cards, 14-day
publishing-trend sparkline, activity feed, and command palette (⌘K).
The block editor — typed-block document rendered server-side through
escape + bluemonday UGC, slash-command palette with opt-in AI-assist, an
inline version-history diff, autosave, and live preview.
As of v1.6.0 the flagship admin (/os) is the only admin surface —
it surpasses Ghost/WordPress/Substack in design and depth while staying a
sovereign single binary with zero CDN dependencies and a strict CSP (no
unsafe-eval, no unsafe-inline). Admin v2 has been removed; the legacy
/admin, /admin/v2 and /admin/v3 paths permanently (301) redirect here
(ADR-0068, ADR-0069 Stage 3).
Design system — hand-authored, CSS-custom-property theming (dark/light/auto),
grouped sidebar, command palette (⌘K), mobile bottom-nav. No inline styles.
Block editor — typed-block document stored as JSON; every block is rendered
to HTML server-side through escape + bluemonday UGC (internal/blockrender),
with no raw-HTML escape hatch. Slash-command palette (with opt-in AI-assist),
inline version-history diff, autosave, ⌘S, and a server-rendered +
DOMPurify-guarded live preview. Legacy posts open losslessly and can be adopted
into blocks via an explicit, reversible Convert to blocks action (ADR-0073),
so a save can never wipe existing content.
Two-factor auth (TOTP) — RFC 6238 in pure stdlib (internal/totp, validated
against the RFC test vectors), enforced on the VayuOS login surface.
Intelligence — native SEO readiness dashboard and a privacy-preserving
analytics page sourced only from the local database.
All interactivity is vanilla JS in same-origin files; the only inline <script>
is the per-request nonce-gated bootstrap, and DOM mutation uses
createElement/textContent — never innerHTML with untrusted data.
Sign in & Sign up
The VayuOS sign-in page (/os/login) — passwordless-friendly, strict-CSP,
self-hosted. The single front door to the whole control panel.
The public reader/member signup page (/signup) — branded, site-themed,
passwordless. A reader enters their email and receives a one-time sign-in link
(the member is created on first use). Zero third-party requests.
Operator consoles — inside VayuOS
As of v1.6.0 the operator consoles below are no longer a separate admin
panel — they render inside the single VayuOS shell under /os/* (an
Operations sidebar section). The legacy /admin/modes, /admin/policy,
/admin/topology, /admin/replay, /admin/faults and /admin/adr page URLs
permanently (301) redirect into VayuOS.
System Modes & Policy Engine
Platform control plane (/os/modes) — 6 adaptive system modes with validated transition graph, append-only mode history, and all registered policies with live pass/warn/fail status.
Policy Provenance Inspector (Ω11)
Live policy evaluation table — per-policy category/severity/result strip, run-history trend, and persistent evaluation log for provenance and trend analysis.
Runtime Topology (Ω9)
Interactive operator console — 17-node live runtime graph (write path, delivery/read, governance, observability) with health derived in real time from failed-job counts, current mode, and fault-escalation state.
Fault escalation surface — active faults with severity level, trigger source, and escalation path through the mode state machine.
ADR Registry
Architecture Decision Records — every design decision indexed with status, date, and rationale. Governance documentation lives in the running system, not a separate wiki.
git clone https://github.com/johalputt/vayupress.git
cd vayupress
sudo ./scripts/deploy-vayupress.sh
What Is VayuPress?
VayuPress ("Vayu" — Sanskrit for wind/speed) is governed publishing infrastructure for developers, writers, and AI-assisted content engines who need:
Adaptive runtime governance — policy-driven system modes (Normal/Degraded/ReadOnly/Recovery/Maintenance/Quarantined) with validated transition graph and operational convergence
VayuPress has an immutable platform kernel — components that define invariants no plugin, extension, or subsystem can bypass. Changes require an RFC and 2/3 supermajority vote.
Component
Package
Invariant
Signing
internal/signing
Every published article has a valid Ed25519 signature
Capability Enforcement
internal/sandbox
Plugin capabilities checked against manifest before every Invoke()
Migration Integrity
internal/migrations
Checksums verified against embedded SQL; drift is a hard error
Identity Model
internal/did
DID:key authentication; no shared-secret fallback
Event Durability
internal/outbox
Events written to outbox in same transaction as state change
Audit Trail
internal/migrations (journal)
Migration journal is append-only; no entry may be deleted
SLO Error Budget
internal/slo
BudgetExhausted() blocks the release gate
Policy Engine
internal/policy
All governance policies registered here; no ad hoc enforcement
VayuPress operates in one of six adaptive system modes, governed by the policy engine:
Mode
Trigger
Effect
normal
Default
All subsystems fully operational
degraded
SLO error budget exhausted
Feature work pauses; writes allowed
read-only
Migration checksum drift
Writes refused; recovery required
recovery
Active recovery operation
Migration apply allowed; writes blocked
maintenance
Operator-initiated
Planned downtime; controlled shutdown
quarantined
Plugin quarantine threshold
Plugin and federation suspended
Transitions are validated against a deterministic graph. Every transition is logged to an append-only history. Policy evaluation drives automatic transitions; operators can force transitions via CLI.
Subprocess IPC pool, Linux seccomp/namespaces, capability enforcement
internal/search
FTS5 + semantic search, Meilisearch client, sharded index
internal/signing
Ed25519 article signing and verification
internal/slo
SLO error budget tracking — rolling windows, exhaustion signals
internal/storage
Content-addressed storage, IPFS stubs
internal/testutil
Shared test helpers
internal/trace
Span-based tracing with correlation/causation IDs
internal/ws
WebSocket/SSE hub for real-time event streaming
Feature List (P1–P27 + Ω1–Ω11)
Core Publishing (P1–P8)
RESTful JSON API for articles (CRUD with slugs, tags, full-text content)
Async write queue — SQLite-backed, crash-safe, with dead-letter replay
Scheduled publishing — stage future-dated posts (RFC3339), promoted through
the normal render/index/cache pipeline by a durable SQLite-backed ticker that
also catches up anything missed during downtime
Sovereign email & newsletter — plain-SMTP delivery on the Go standard
library (no third-party SDKs, no hosted senders), double opt-in confirmations,
and one-click broadcasts with auto unsubscribe links; a safe no-op until
SMTP_HOST is set
Automatic image optimization — stdlib-only (no libvips/CGO) downscaling of
oversized PNG/JPEG editor uploads with area-averaging resampling; GIF/WebP pass
through untouched
Sovereign rich media (ADR-0070) — embed blocks unfurl any URL into a
self-hosted link card; YouTube/Vimeo render as privacy-first click-to-load
facades (no third-party request until the reader clicks). A pure-Go Mermaid→SVG
engine compiles six diagram grammars (flowchart, sequence, pie, state,
class, gantt) server-side with zero client JavaScript. Every server-side fetch
goes through the SSRF-hardened safefetch client; all output is bluemonday-
sanitised with no raw-HTML escape hatch
Sitemap XML, RSS feed, and robots.txt auto-generation
In-memory render cache with static-file output via Nginx
SQLite WAL mode with adaptive checkpointing
Migration checksum drift detection — halts startup on tampering
Immutable WORM audit log via SQLite ABORT triggers
Plugin hook system with worker pool, panic recovery, and circuit-breaker disable
Security & Governance (P9–P13)
Multi-author accounts & password login — Argon2id-hashed credentials,
server-side SQLite sessions (only token SHA-256 stored), hardened
HttpOnly/SameSite=Lax cookie; admin pages accept an API key or a login
session. Bootstrap via vayupress user add … --admin
Automated CI governance — 15+ CI jobs, ci-pass gate
Ethical AI Charter in ETHICS.md (no training on user data, no telemetry)
Multi-Package Architecture (P14–P19)
35+ internal/ packages with compiler-enforced boundaries
App struct owns all mutable runtime state — no package-level globals
Repository pattern: ArticleRepo interface backed by SQLite
Integration test harness with go test -race ./...
Integrations & Insight (Tier 2)
Privacy-first analytics — cookieless, consent-free page-view counting with
zero PII (no IPs, UAs, cookies, or per-visitor rows); only daily aggregates per
path/referrer. GET /api/v1/admin/analytics
Outbound webhooks — HMAC-SHA256-signed JSON POSTs on
article create/update/delete to Zapier/n8n/Make/custom services, with bounded
retry and a per-hook delivery audit trail
Social auto-posting — newly published articles auto-share to
Mastodon/Pleroma/Akkoma via a single app token (no OAuth dance), async and
best-effort with idempotency
Built-in Ghost & WordPress importers — vayupress migrate ghost --file …
and vayupress migrate wordpress --file … move content off both platforms with
no external tooling (titles, slugs, dates, tags, draft status preserved)
Sovereign AI writing assistant — summarize / improve / titles / SEO /
continue, powered by a local Ollama server (no hosted model, no telemetry).
Suggest-only — never auto-edits. POST /api/v1/admin/ai/assist
Memberships & paywalls — passwordless magic-link reader login, per-article
access levels (public/members/paid) with preview + CTA, and an optional
signature-verified Stripe webhook for paid upgrades (no embedded payment SDK)
Event-Driven Reliability (P20–P22)
Transactional outbox — events written atomically with article mutations
lifecycle.Manager — ordered startup/shutdown with registered components
Typed event structs with versioned schemas (article.created.v1)
Idempotent dispatch via delivered_events deduplication table
Observability & Tracing (P22–P23)
Structured JSON logging with LogFields — correlation/causation IDs on every line
Span-based tracing: Start, SetAttribute, End
SLO error budgets with rolling windows — 5 production SLOs tracked
Resource Governance & Sandboxing (P24–P26)
Named semaphore limiters (articles.write, plugin.exec)
Subprocess IPC pool for out-of-process plugin execution
Linux seccomp filtering and namespace isolation for subprocess plugins
Capability enforcement — subprocess plugins run with dropped privileges
Runtime Topology (/admin/topology) — 17-node live health graph
Ω10 — Live-streaming timeline + Replay Explorer — animated causal arrows, STREAMING poller, and a dead-letter / poison-queue inspector (/admin/replay) with single-job and batch requeue
Ω11 — Policy Provenance Inspector (/admin/policy) — SQLite-journaled policy evaluations (policy_evaluations table), live pass/warn/fail status, run-history trend sparkline, and a persistent provenance log of every policy run
Theme & Site Settings Control Panel (/admin/theme)
A governed customisation surface — every input is validated, no raw markup is
trusted, and the strict CSP stays intact:
Identity — site name, tagline, meta description, author. Baked into every
public page; a save triggers a full rendered-cache purge so changes propagate.
Palette — light/dark primary + accent colours (hex-validated). Rendered as
Pico CSS-variable overrides and served same-origin at /theme.css (ETag +
short max-age) — never inlined, so style-src 'self' holds. The first-deploy
defaults match the vendored custom.css, so there is no flash-of-unstyled-content.
Studio — a sovereign design-token theme system (ADR-0070, internal/theme):
a typed 23-field token schema, a hex-validated CSS-variable compiler, and eight
system-font presets (Default, Aurora, Slate, Terminal, Sepia, Carbon, Ocean,
Sakura). The Studio tab shows a preset gallery and a live preview that
re-themes instantly via CSSOM setProperty — no inline <style>, no style=
attributes, so the strict CSP is untouched. Apply persists to theme_tokens
(migration 029), recompiles /theme.css, and purges the render cache. API:
GET/POST /api/v1/admin/theme/{presets,tokens,preview,apply} (auth + CSRF).
Custom CSS — operator stylesheet, 16 KB cap, folded into /theme.css.
Cannot reach external origins or execute scripts (CSP-contained).
Head & SEO — declarative, allowlisted capabilities (keywords, theme-color,
robots, Google/Bing verification) rendered to escaped <meta> tags. Raw <head>
HTML is intentionally not accepted — meta-refresh redirects, external
beacons, and <base> hijacks are structurally impossible, not merely filtered.
Storage & safety — persisted in the site_settings table (migration 006,
content-checksummed like every migration); writes are CSRF-protected, blocked in
read-only/quarantined modes, and audit-logged (component: "theme").
Public theme toggle — a sun/moon switch in the site header persists the
reader's choice in localStorage; served as a same-origin script so it needs no
CSP nonce (which cached HTML cannot carry).
CSP telemetry — violations report to POST /csp-report, incrementing
vayupress_csp_violations_total and logging the offending directive, so runtime
CSP drift is observable rather than silent.
API Endpoints Overview
Method
Path
Description
GET
/api/articles
List articles (paginated, filterable by tag)
POST
/api/articles
Create article (async write queue)
GET
/api/articles/{slug}
Get article by slug
PUT
/api/articles/{slug}
Update article
DELETE
/api/articles/{slug}
Delete article
GET
/api/search?q=...
Full-text search (Meilisearch or SQLite fallback)
GET/POST
/api/v1/graphql
Read-only GraphQL content API (query-only — no mutations) (ADR-0067)
GET
/api/v1/i18n/{lang}
Merged i18n message bundle for a language (public)
GET
/api/v1/stream
Real-time SSE feed of article events (API-key-gated)
Governance error-budget state + recommended escalation
GET
/api/v1/admin/search/drift
Search-index vs article-store drift report
POST
/admin/search/reindex
Rebuild the search index from the store (CSRF-protected)
POST
/api/v1/admin/newsletter/broadcast
Email all confirmed subscribers (CSRF-protected)
GET
/api/v1/admin/schedule
List staged scheduled posts
POST
/api/v1/admin/schedule
Stage a future-dated post (CSRF-protected)
DELETE
/api/v1/admin/schedule/{id}
Cancel a scheduled post (CSRF-protected)
GET
/api/v1/admin/users
List author accounts (admin role)
POST
/api/v1/admin/users
Create an account (admin role, CSRF-protected)
DELETE
/api/v1/admin/users/{email}
Delete an account (admin role, CSRF-protected)
POST
/os/login
Email + password sign-in (issues session cookie)
POST
/os/logout
Destroy the current session
GET
/api/v1/admin/analytics
Privacy-first page-view summary (cookieless)
GET
/api/v1/admin/webhooks
List outbound webhooks
POST
/api/v1/admin/webhooks
Register a webhook (CSRF-protected)
DELETE
/api/v1/admin/webhooks/{id}
Delete a webhook (CSRF-protected)
GET
/api/v1/admin/webhooks/{id}/deliveries
Webhook delivery audit trail
GET
/api/v1/admin/ai/status
AI assistant availability + supported ops
POST
/api/v1/admin/ai/assist
Run a local-LLM writing operation (CSRF-protected)
POST
/api/v1/members/login
Request a passwordless member sign-in link
GET
/members/verify
Consume a magic link, start a member session
GET
/api/v1/admin/members
List members + tier counts
PUT
/api/v1/admin/members/{email}/tier
Set a member's tier (CSRF-protected)
PUT
/api/v1/admin/articles/{slug}/access
Set article access level (CSRF-protected)
POST
/api/v1/stripe/webhook
Signed Stripe webhook → paid upgrades (optional)
Public theming endpoints (no auth): GET /theme.css (operator palette + custom
CSS, served same-origin for CSP), GET /static/js/theme-toggle.js (sun/moon
switcher), POST /csp-report (CSP violation telemetry → vayupress_csp_violations_total).
Imports write both the sanitised article and an article_sources side-car so
the VayuOS block editor can reopen each post losslessly. See
docs/MIGRATION.md for the full guide.
Standalone migration and import tools live under tools/. Each is an
independent Go module — builds without pulling in the engine.
All migration tools share the same design: direct source access (no API keys needed), keyset pagination, throttled batching, checkpoint/resume, and idempotent INSERT OR IGNORE writes.
Operational Tools
Tool
Purpose
Source
vayu-backup
Compress, verify, and restore VayuPress SQLite databases
# Migrate from Ghost
cd tools/ghost-to-vayu && go build -o ghost2vayu ./cmd/ghost2vayu
./ghost2vayu migrate --ghost-driver mysql \
--ghost-dsn "user:pass@tcp(localhost:3306)/ghost_production" \
--vayu-db /var/lib/vayupress/vayupress.db
# Import Markdown posts
cd tools/markdownfolder2vayu && go build -o md2vayu ./cmd/md2vayu
./md2vayu import --dir ./posts --vayu-db /var/lib/vayupress/vayupress.db
# Validate after migration (exits 1 on errors — CI-safe)
cd tools/vayu-validate && go build -o vayu-validate ./cmd/vayu-validate
./vayu-validate validate --db /var/lib/vayupress/vayupress.db
Built-in Plugin Features
These features are part of VayuPress core (no external service required):
Feature
Package
API
SEO Optimizer
internal/seo
Auto OpenGraph, Twitter Card, JSON-LD per article
Comments
internal/comments
POST /api/v1/articles/{slug}/comments + moderation
Article Versions
internal/versions
GET /api/v1/admin/articles/{slug}/versions
Series/Collections
internal/collections
GET/POST /api/v1/collections
Newsletter
internal/newsletter
POST /api/v1/newsletter/subscribe
Webmentions
internal/webmention
POST /webmention (W3C receiver)
Draft Preview Links
internal/preview
POST /api/v1/admin/preview
Redirect Manager
internal/redirects
GET/POST /api/v1/admin/redirects
Table of Contents
internal/toc
GET /api/v1/articles/{slug}/toc
ActivityPub / Federation
internal/federation
Outbox relay + HTTP Signatures
Spam Guard
internal/spam
Comment classification middleware
Content Signing
internal/signing
HMAC article verification
Sovereign Self-Update
internal/update
Check-only web API + signature-verified CLI apply
Admin UI — VayuOS (/os)
VayuOS is the single, editor-first admin on a fully vendored, CSP-compliant
stack (no CDNs, no unsafe-eval, per-request nonces). The typed block editor
has AI-assist, inline version-history diff, live preview, a command palette
(⌘K), distraction-free mode, word count / reading time, an SEO readiness meter
and autosave. The historical Admin v2 (/admin/v2, ADR-0065) was removed in
v1.6.0 (ADR-0069 Stage 3); its routes now permanently redirect to /os. See
docs/ADMIN-UI.md,
ADR-0068 and
ADR-0069.
Self-Update
VayuPress can check for and apply its own updates sovereignly and safely:
The web panel can only check (GET /admin/api/updates/check). Applying an
update is CLI-only, requires opt-in (VAYU_SELFUPDATE_ENABLED=true) and an
operator-pinned Ed25519 key (VAYU_RELEASE_PUBKEY), is refused in
read-only/quarantine/maintenance mode, backs up the database first, and never
auto-restarts. See docs/UPGRADING.md,
docs/SECURITY.md, and
ADR-0064.
Requirements
Requirement
Detail
Go
1.23+ (build from source; deploy script installs 1.25)
CGO / SQLite3
gcc required (libsqlite3-dev or bundled via go-sqlite3)
OS
Ubuntu 24.04 LTS (recommended); Linux kernel 5.x+ for sandbox features
RAM
8 GB minimum, 12 GB recommended
CPU
4 vCPU minimum, 6 vCPU recommended
Disk
50 GB NVMe minimum, 250 GB for 1M+ posts with media
Access
Root or sudo for deploy script
Deployment
Automated (recommended)
# Download and run the deploy script
curl -sSL https://raw.githubusercontent.com/johalputt/vayupress/main/scripts/deploy-vayupress.sh | bash
# Dry-run first (inspect what will be installed)
bash scripts/deploy-vayupress.sh --dry-run
# Upgrade an existing installation
bash scripts/deploy-vayupress.sh --upgrade
The deploy script handles: Go toolchain, CGO/SQLite3, binary build, Nginx with TLS and CSP, systemd service, Meilisearch (optional), nightly backup cron, fail2ban rules.
Manual Build
git clone https://github.com/johalputt/vayupress.git
cd vayupress
go build -race ./... # development build
go build -ldflags="-s -w" -trimpath ./cmd/vayupress # production binary
Development Setup
git clone https://github.com/johalputt/vayupress.git
cd vayupress
go build ./... # build all packages
go test -race ./... # full test suite with race detector
go vet ./... # static analysis
gofmt -l . # format check
make build test lint # all-in-one
Real numbers from the in-process load benchmark (POST /admin/benchmark) on a
4-vCPU Intel Xeon @ 2.80 GHz, 16 GB box, SQLite in WAL mode, 20 concurrent
readers against the cached render path:
Metric
Measured
Target
Result
Read p50
16 ms
—
—
Read p95
16 ms
<50 ms
✅ PASS
Read p99
16 ms
<50 ms
✅ PASS
Read throughput
~8,700 RPS
—
—
Read mean
8.2 ms
—
—
Measured — micro-benchmarks (go test -bench)
Operation
Package
ns/op
allocs/op
Ed25519 sign
internal/signing
28,423 (28.4 µs)
7
Ed25519 verify
internal/signing
64,133 (64.1 µs)
4
Article input validation
internal/api
234
0
Slug validation
internal/api
384
0
Migration apply (full)
internal/migrations
142,151 (142 µs)
102
Event schema validate
internal/events/schema
196
0
Merkle proof generation
internal/merkle
1,403
20
Histogram record (metrics)
internal/metrics
18.3
0
Cache hit-ratio read
internal/metrics
0.46
0
Hot-path validation and metrics are zero-allocation. Reproduce with:
make bench # committed baselines
go test -bench=. -benchmem -run=^$ ./... # full micro-benchmark sweep
curl -X POST -H "X-API-Key: $KEY" .../admin/benchmark # live end-to-end load
The Apache-2.0 license adds an explicit patent grant and trademark terms on top
of a permissive core, which makes adoption inside organizations clearer than a
bare MIT grant. Bundled third-party components retain their own licenses
(see NOTICE).
Command webhook-notify is an example VayuPress sandbox plugin that POSTs a compact JSON notification to an external URL whenever an article hook fires.
Command webhook-notify is an example VayuPress sandbox plugin that POSTs a compact JSON notification to an external URL whenever an article hook fires.
Package budget implements governance error budgets: bounded windows of severity-classified events that accumulate "debt" and, once exhausted, imply a defined escalation.
Package budget implements governance error budgets: bounded windows of severity-classified events that accumulate "debt" and, once exhausted, imply a defined escalation.
Package i18n provides lightweight internationalisation for the public site: a message catalog keyed by BCP-47 language tag, with HTTP Accept-Language negotiation.
Package i18n provides lightweight internationalisation for the public site: a message catalog keyed by BCP-47 language tag, with HTTP Accept-Language negotiation.
Package policy is the Platform Policy Engine — a single authoritative system that evaluates architecture, release, compatibility, reliability, and security policies.
Package policy is the Platform Policy Engine — a single authoritative system that evaluates architecture, release, compatibility, reliability, and security policies.
Package provenance defines VayuPress's epistemic confidence vocabulary and the rules for how confidence propagates when one operational fact is derived from others.
Package provenance defines VayuPress's epistemic confidence vocabulary and the rules for how confidence propagates when one operational fact is derived from others.
Package safefetch is the single, SSRF-hardened HTTP fetcher used for every server-side outbound request that carries an operator- or author-influenced URL (embed resolution, remote-image import, oEmbed/OpenGraph metadata).
Package safefetch is the single, SSRF-hardened HTTP fetcher used for every server-side outbound request that carries an operator- or author-influenced URL (embed resolution, remote-image import, oEmbed/OpenGraph metadata).
Package totp implements TOTP (RFC 6238) and the underlying HOTP (RFC 4226) using only the Go standard library — no third-party dependencies, in keeping with VayuPress's sovereign single-binary posture.
Package totp implements TOTP (RFC 6238) and the underlying HOTP (RFC 4226) using only the Go standard library — no third-party dependencies, in keeping with VayuPress's sovereign single-binary posture.
Package trace propagates request-scoped observability identifiers through context.Context so that every log line, event, and queue job can be correlated back to the originating HTTP request (ADR-0053).
Package trace propagates request-scoped observability identifiers through context.Context so that every log line, event, and queue job can be correlated back to the originating HTTP request (ADR-0053).
Package webhooks delivers outbound HTTP notifications when content changes, enabling integrations with automation platforms (Zapier, n8n, Make) and custom services without coupling VayuPress to any of them.
Package webhooks delivers outbound HTTP notifications when content changes, enabling integrations with automation platforms (Zapier, n8n, Make) and custom services without coupling VayuPress to any of them.