f451: Dokumentation ohne Handschellen

f451: Dokumentation ohne Handschellen

Dokumentation landet oft dort, wo sie am schwersten wieder herauskommt. In SharePoint oder Confluence, in einem Format, das außerhalb der Plattform nur mit Verlusten lesbar ist. Wer wechseln will, exportiert und flickt. Wer wissen will, wer eine Betriebsanweisung wann geändert hat, findet eine Versionshistorie, aber ohne Zusatzmodule meist keine Freigabe. Die Änderung war sofort live.

f451 ist meine Antwort darauf. Ein Wiki mit Seitenbaum, Suche, Editor und Freigaben, dessen Inhalte vollständig als Markdown in Git-Repositories liegen. KI-Agenten wie Claude Code arbeiten über einen mitgelieferten MCP-Server mit, die Standardschnittstelle für Agenten-Werkzeuge. Sie lesen, suchen und schreiben Entwürfe unter dem Konto des Menschen, der sie einsetzt, mit denselben Rechten und demselben Review-Weg. Seit dem 28. September ist das Projekt öffentlich, mit Quellcode auf GitHub und einer Live-Demo.

Der Name ist eine Verbeugung vor Ray Bradburys Fahrenheit 451, dem Roman über eine Gesellschaft, die Bücher verbrennt. Dokumente, über die ihre Autoren selbst verfügen, sind das Gegenprogramm.

Git als einzige Quelle

Was im Repository steht, gilt. Alles andere leitet f451 daraus ab. Ein Space ist ein Repo auf Forgejo, einer selbst gehosteten Git-Plattform, oder auf GitHub. Eine Seite ist ein Ordner mit einer index.md, Unterseiten sind Unterordner, Bilder und Diagramme liegen in _media/ direkt neben der Seite.

space-repo/
├── space.yaml
├── _templates/
│   └── meeting-notiz.md
├── betrieb/
│   ├── index.md
│   ├── _media/architektur.drawio.svg
│   └── deployment/index.md

Das Frontmatter enthält nur eine stabile id, Titel, Tags, optional die Sprache und typisierte Beziehungen zu anderen Seiten.

---
id: 8f3ka2
title: Deployment
tags: [betrieb, kubernetes]
lang: de
relations:
  depends_on: [betrieb/monitoring]
---

Relative Links funktionieren unverändert in der Weboberfläche von Forgejo, in Obsidian und in jedem Texteditor. Die [[Wikilinks]] aus dem Editor versteht Obsidian direkt, Forgejo zeigt sie als Text. Die Dokumentation bleibt lesbar, auch wenn f451 einmal nicht mehr läuft.

PostgreSQL ist in dieser Architektur nur ein Index. Beim Push holt f451 die geänderten Dateien, extrahiert Links, Tags und Metadaten und rendert jede Seite einmal zu HTML. Geht die Datenbank verloren, baut reindex --all den Index aus Git neu auf. Verloren sind dann nur Sitzungen, Sperren und Kontoverknüpfungen, die Nutzer mit einer neuen Anmeldung wiederherstellen. Die Inhalte hängen allein am Repository.

Postgres statt SQLite habe ich wegen der Suche gewählt. Die Volltextsuche soll deutsche und englische Wörter auf ihren Stamm zurückführen, und Postgres bringt dafür Konfigurationen für beide Sprachen mit. Die Volltextsuche von SQLite, FTS5, kennt nur ein Verfahren für englische Wörter. Deutsche Wörter würden nicht auf ihren Stamm gekürzt, und die Suche nach „Server“ fände „Servern“ nicht.

Entwurf, Review, Merge

Im Wiki schreibt niemand direkt auf die veröffentlichte Fassung. Jede Änderung beginnt als Entwurf, und der Entwurf ist ein Branch draft/<pageId>. Wer eine Freigabe anfordert, öffnet einen Pull Request. Die Freigabe selbst ist ein Merge. Leser sehen währenddessen den freigegebenen Stand, Autoren arbeiten parallel am Entwurf.

Zustand im WikiAbbildung in Git
In BearbeitungBranch draft/<pageId> existiert
Im Reviewoffener Pull Request auf diesem Branch
FreigegebenStand auf main

Die Zustände stehen nirgends in der Datenbank. f451 leitet sie bei jeder Abfrage aus der Existenz des Branches und der Suche nach einem offenen Pull Request ab. Ein zweites Statusfeld könnte irgendwann vom tatsächlichen Stand in Git abweichen, und dann wüsste niemand mehr, welcher Angabe er glauben soll.

Vor der Freigabe zeigt eine Review-Ansicht die Änderung als visuellen Vergleich, blockweise und auf Wunsch als Wort-Diff auf der Markdown-Quelle. Ist main seit Beginn des Reviews weitergelaufen, sperrt f451 die Freigabe sichtbar, bis der Entwurf aktualisiert ist. Dabei wird ausdrücklich gewählt, ob der neue Stand übernommen oder die eigene Fassung behalten wird. Stilles Überschreiben ist nicht vorgesehen.

Rechte kommen vom Repository

f451 hat kein eigenes Rollenmodell. Wer ein Repo lesen darf, sieht den Space. Wer schreiben darf, darf Entwürfe anlegen. Wer mergen darf, darf freigeben. Der Code enthält dafür kein Feld und keine Tabelle. Ob jemand freigeben darf, entscheidet allein der Git-Provider. Lehnt er den Merge mit 403 ab, ist die Frage beantwortet.

Die Anmeldung läuft über OpenID Connect, wahlweise mit Microsoft Entra ID, Forgejo oder einem anderen OIDC-Provider. Danach verknüpft jeder Nutzer sein Forgejo- oder GitHub-Konto. Commits entstehen unter diesem persönlichen Konto und nie unter einem Service-Account. Die Git-Historie einer Seite zeigt deshalb, wer sie tatsächlich geändert hat, und nicht, dass „das Wiki“ sie geändert hat.

Die Dokumente liegen in den eigenen Repositories. Wer ausscheidet, verliert mit dem Git-Konto auch den Zugriff. Es gibt keinen Sync-Client, der Kopien auf jeden Laptop verteilt. Lokale Clones entstehen nur dort, wo jemand bewusst einen anlegt.

Ein Editor, der nichts still verändert

Wer nicht mit Git arbeitet, soll trotzdem schreiben können. Der Editor hat deshalb einen WYSIWYG-Modus auf Basis von Tiptap (ProseMirror) mit Toolbar und [[-Autovervollständigung für Links auf andere Seiten. Ein Slash-Menü fügt Überschriften, Tabellen, Hinweisboxen und Bilder ein. Daneben gibt es einen Roh-Modus mit CodeMirror für das vollständige Dokument inklusive Frontmatter.

Der heikle Teil ist der Weg zwischen beiden. Ein WYSIWYG-Editor, der Markdown liest und wieder schreibt, verändert gern unbemerkt Formatierungen. f451 prüft deshalb vor jedem Wechsel in den WYSIWYG-Modus, ob sich das Dokument verlustfrei darstellen lässt. Enthält es etwa rohes HTML oder Fußnoten, verweigert der Editor den Wechsel mit Begründung. Ändert sich beim Wechsel nur die Schreibweise, etwa * statt - in Listen, warnt er. Parsen und Serialisieren laufen durch dieselbe Markdown-Pipeline wie die Leseansicht, und ein Testkorpus aus Beispielseiten in einheitlicher Schreibweise muss den Weg Markdown → Editor → Markdown byte-identisch überstehen.

Der Rest ist Schutz gegen Alltagsstörungen: Autosave nach 30 Sekunden, ein sichtbarer Konfliktdialog, wenn jemand anderes zwischenzeitlich gespeichert hat, eine weiche Sperre für zwei Minuten, der vor gleichzeitigem Bearbeiten warnt, ohne es zu verbieten. Fällt die Verbindung weg, puffert der Editor die Änderungen lokal im Browser und schiebt sie nach, sobald der Server wieder erreichbar ist. Das Nachschieben läuft über denselben Speicherweg mit Konfliktprüfung, und beim Wiederöffnen einer Seite spielt der Editor einen Puffer nie still ein, sondern fragt nach.

Dazu kommen Vorlagen pro Space, Diagramme mit draw.io und Excalidraw, die direkt in der Seite bearbeitbar bleiben, ein Wissensgraph über Links, Hierarchie und Beziehungen, ein Bericht über kaputte Links sowie eine deutsche und englische Oberfläche mit Hell- und Dunkelmodus.

KI-Agenten über denselben Review-Weg

Der MCP-Dienst von f451 ist ein zustandsloser Übersetzer zwischen MCP und der HTTP-API und stellt derzeit 16 Werkzeuge bereit, von search_wiki und read_page über edit_page und update_page_draft bis request_review.

Weil die Seiten reines Markdown sind, lesen und schreiben Agenten sie ohne Konvertierung.

Agenten bekommen keinen Sonderweg. Sie melden sich mit einem persönlichen API-Token an und schreiben unter dem Konto des Menschen, der sie einsetzt. Ihre Änderungen beginnen als Entwurf wie jede andere. Technisch darf ein Agent damit genau das, was sein Mensch darf, also auch über release_page freigeben, wenn dieser Merge-Rechte hat. Davon abhalten kann ihn nur die mitgelieferte Prompt-Vorlage, die die Freigabe einem Menschen überlässt.

Eigens für Agenten gebaut ist save_diagram. Der Agent schickt kein SVG und kein Mermaid, sondern eine Beschreibung aus Bahnen und Schritten. Die Anordnung berechnet der Dienst und nicht das Sprachmodell, der Agent fügt nur den zurückgegebenen Markdown-Schnipsel in die Seite ein.

Architektur und Entstehung

f451 ist ein pnpm-Monorepo in TypeScript mit drei Anwendungen (API, Weboberfläche, MCP-Dienst) und gemeinsamen Paketen.

TeilAufgabe
apps/api (Fastify)Indexierung, Lese- und Schreib-Endpunkte, Review-Workflow, Rechteprüfung, Webhooks
apps/web (Next.js)Oberfläche, leitet /api, /auth und /media an die API weiter
apps/mcpZugang für KI-Agenten
packages/markdowneine gemeinsame Markdown-Pipeline für Lesen und Schreiben
packages/editorEditor-Kern auf ProseMirror/Tiptap
packages/git-providerAdapter für Forgejo und GitHub
packages/design-tokensFarben, Schrift und Abstände als Token-Katalog

Der Git-Provider-Adapter ist die kritischste Schnittstelle. Beide Implementierungen, Forgejo und GitHub, müssen dieselbe Contract-Test-Suite bestehen, eine gemeinsame Testsammlung, die das Verhalten der Schnittstelle festschreibt. Alles darüber kennt nur das Interface.

Die Design-Spezifikation stammt vom 9. Juli 2026, danach entstand f451 in Phasen, von der Leseansicht über Editor-Kern, Editor-Oberfläche und Review-Workflow bis zu Vorlagen und Resilienz, jede Phase mit Abnahme über End-to-End-Tests in Playwright. Diese Tests fahren einen frischen Stack aus Postgres- und Forgejo-Containern hoch und prüfen den Review-Ablauf mit einer echten zweiten Identität, nicht mit einem Admin-Token.

Die Entwicklung lief mit Claude Code. Der Code umfasst rund 80.000 Zeilen TypeScript, davon etwa 35.000 in Tests (Eigenzählung mit wc -l, inklusive Leer- und Kommentarzeilen). Wie das Projekt entstanden ist, steht in der Entwicklungschronik im Repo.

Live-Demo und Schnellstart

Unter f451.rotecodefraktion.de läuft eine öffentliche Instanz. Die Anmeldung geht über Forgejo mit zwei Demo-Konten.

KontoPasswortRechte
demoda9d33b2efdb41edliest alle Spaces
writer43dc099d5da028f4schreibt zusätzlich im Playground

Die Demo wird jede Nacht zurückgesetzt. Sie enthält die Dokumentation von f451 selbst, aufgeteilt in User Guide, Developer Guide und Admin Guide, dazu einen Playground zum Ausprobieren von Entwurf und Review.

Lokal braucht f451 Docker oder Podman, Node 22 und pnpm 9. Forgejo und das Wiki müssen für Browser und Container unter derselben Adresse erreichbar sein. localhost funktioniert nicht, weil es im Container auf den Container selbst zeigt. Mit der LAN-Adresse des Rechners als <IP> sieht der Ablauf so aus.

git clone https://github.com/rotecodefraktion/f451.git && cd f451

cat > deploy/git/docker-compose.override.yml <<EOF
services:
  forgejo:
    environment:
      FORGEJO__server__ROOT_URL: http://<IP>:3300/
EOF
docker compose -f deploy/git/docker-compose.yml up -d

FORGEJO_URL=http://<IP>:3300 WEB_BASE=http://<IP>:8080 ./scripts/dev-local-setup.sh

cd deploy/wiki && docker compose up -d --build

Das Setup-Skript legt einen Admin, eine Organisation, eine OAuth-App und einen Demo-Space an. Danach unter http://<IP>:8080 über Forgejo anmelden und unter Settings → Connections das Forgejo-Konto verknüpfen. Erst dann werden die Spaces sichtbar. Dieses Setup ist nur für die lokale Entwicklung gedacht. Für den Produktivbetrieb beschreibt deploy/BETRIEB.md Umgebungsvariablen, Backup, Wiederherstellung und ein Runbook für Störungsfälle.

Lizenz

f451 ist source-available, nicht Open Source im Sinne der OSI. Die Lizenz baut auf der PolyForm Shield License 1.0.0 auf und ergänzt sie um eigene Bedingungen. Der Volltext steht in der LICENSE.md.

Nutzen, verändern und weitergeben darf f451 grundsätzlich jeder kostenlos, Unternehmen eingeschlossen. Auch bezahlte Dienstleistungen rund um f451, also Installation, Anpassung und Betrieb für jemanden, der es selbst nutzt, sind frei. Eine Lizenz braucht nur, wer f451 oder eine veränderte Fassung verkauft oder als bezahlten gehosteten Dienst anbietet. Jede Installation muss den Hinweis „Based on f451 by www.rotecodefraktion.de“ sichtbar zeigen.

Ausgeschlossen von der Nutzung sind die rechtsextreme AfD, ihre angegliederten Organisationen und die in der Lizenz genannten demokratiefeindlichen Organisationen und Plattformen.

Quellen