Demo content from demo/developer-guide (0c17989)

This commit is contained in:
f451-admin 2026-09-29 18:52:55 +02:00
parent e7b15ff117
commit 4e32950ceb
12 changed files with 676 additions and 2 deletions

65
principles/index.md Normal file
View file

@ -0,0 +1,65 @@
---
id: principles
title: Principles
description: The four rules that shape f451's design, and why they exist.
tags: [architecture, principles]
lang: en
---
# Principles
Four rules recur throughout the codebase. They are not style preferences —
each one closes off a class of bugs or design mistakes that the project has
already made once.
## Git is the source of truth, Postgres is only an index
Every space is a Git repository; every page is a Markdown file with
frontmatter. Postgres holds the rendered content, the search vector, the
knowledge-graph edges, sessions and encrypted provider tokens — nothing
that can be derived from Git is allowed to live *only* in the database.
> [!IMPORTANT]
> Losing `pg-data` is recoverable: `POST /admin/reindex` or the drift job
> rebuilds the index from Git. Losing `forgejo-data` is not — that is the
> one thing backups exist for. If you find yourself adding a column that
> holds information not derivable from the Git content, stop and ask
> whether it belongs in Git instead.
## Permissions come from the Git provider
f451 has no role system of its own. Whether someone can see a space or
write to it is decided by their permissions on the underlying repository.
Writers always write with **their own** provider token — the API never
commits under a service account. Without a linked provider account, every
write attempt fails with 403; that is a precondition, not a bug.
This also shapes how "not found" behaves: a `404` deliberately means
*"doesn't exist, or you don't have access"* — never distinguish the two.
Doing so would let an unauthorized caller learn that a page exists, which
is exactly the kind of existence oracle this design avoids.
## Writing always goes through the review workflow
There is no route that writes directly to the published version — not for
people, not for agents. The path is always: create a draft (a branch) →
write → open a review (a pull request) → approve (merge) → reindex.
Draft routes carry a SHA contract: whoever writes names the `baseSha` of
the version they started from. If the content has changed underneath them,
they get a `409` back with the current state instead of a silent
overwrite. See [[api]] for the routes that implement this.
## Diagrams carry their own source
`.drawio.svg` and `.excalidraw.svg` files under `<page folder>/_media/` are
plain SVGs that also carry the diagram's source XML in a `content`
attribute. One file is both the picture people see and the thing the
diagram editor reopens. The SVG sanitizer keeps that attribute and the
wrapping text elements deliberately — stripping either would make the
diagram unreadable or unopenable.
> [!TIP]
> These four rules are the first thing to check when a design choice looks
> surprising: it is very likely a direct consequence of one of them, not an
> arbitrary decision.