Operator Wiki — Schema
The contract for every page under
wiki/. If a page violates this schema, the page is wrong — not the schema.Last updated: 2026-07-24
Purpose
This wiki is an internal operator reference for the migration that
moves api.legendary-arena.com and its PostgreSQL off Render onto a
self-hosted DigitalOcean Ubuntu droplet fronted by Cloudflare. Each
page is an entity (a host subsystem, an infra artifact, a
migration concept, or an operational procedure) with a defined shape,
cross-references to related entities, and citations to the
authoritative artifacts that govern it.
The wiki exists to answer:
- “What is X, and which file in this repo owns it?”
- “Which plan phase and infra script govern X?”
- “What does X interact with, and what edge cases bite during cutover?”
It is not a replacement for docs/PLAN.md
, the
infra/ artifacts themselves, or the operator runbooks under
content/
. The wiki explains; the cited artifacts
govern and execute.
Authority Position
The wiki is documentation. It cites authoritative sources; it does not redefine them. The authority hierarchy for this repo:
1. .claude/CLAUDE.md # repo identity + working model
2. docs/PLAN.md # migration plan & repo blueprint
3. docs/01-REPO-FOLDER-STRUCTURE.md # repo map
4. infra/** and .github/workflows/** # executable artifacts (the source of truth)
5. content/** # operator runbooks
6. (this wiki)
7. Active conversation context
If the wiki and a higher-authority artifact disagree, the wiki is
wrong and must be corrected. Wiki pages never override the plan, the
scripts, or the workflows. The wiki itself is never a valid
source citation in another wiki page.
The core rebuild invariant lives in the plan, not here: “rebuild the
host from documentation alone” reduces to “run the numbered
infra/scripts/*.ps1 files in order” (see
PLAN.md §0
). The wiki describes what each script
does; the script is the thing that runs.
Scope Exclusion
The wiki is descriptive, not prescriptive. It explains the migration; it does not govern it.
A wiki page MUST NOT:
- Redefine decisions from
docs/PLAN.md(droplet size, region, TLS posture, deploy mechanism, etc.). The wiki cites the locked-decisions table; it does not re-decide. - Restate a script line-for-line as if the wiki were the source.
Cite the script and describe its behaviour; the script under
infra/is the executable truth. If the wiki and the script drift, fix the wiki. - Introduce new constraints that don’t exist in the plan or the artifacts. If you find yourself writing “the operator MUST do X” and X isn’t already in PLAN.md, a script, or a runbook, stop — the wiki is the wrong place.
If a wiki page drifts into prescriptive territory, the fix is to either (a) move the prescriptive content into the plan or the owning artifact and cite it, or (b) delete it.
File Layout
wiki/
├── SCHEMA.md # this file — the contract
├── README.md # purpose, conventions, authority
├── INDEX.md # categorized list of all pages
└── <slug>.md # entity pages (one per entity)
SCHEMA.md, README.md, and INDEX.md are reserved filenames. All
other *.md files in wiki/ are entity pages and must conform to
this schema.
There are no subdirectories. Categorization is by type and
surfaced in INDEX.md. (The rendered operator wiki under content/
uses Hugo sections; this wiki/ knowledge layer is deliberately flat,
like the engine repo’s wiki/ that inspired it.)
Flat-structure cap
The flat layout is valid up to 50 entity pages. Beyond 50, a formal SCHEMA amendment must introduce partitioning before any further pages are added.
File Naming
- Filename = title, kebab-cased. Lowercase, replace spaces with
-, drop characters outside[a-z0-9-], collapse consecutive hyphens.title: SSH Hardening→ssh-hardening.mdtitle: Cloudflare TLS→cloudflare-tls.md
- Singular by default.
- No leading numbers, no prefixes —
INDEX.mdorders pages, not the filesystem. (Note: the scripts are numbered —05-…,10-…— because execution order matters there; wiki slugs are not.) - No spaces, no underscores, no special characters other than hyphens.
- Reserved files are ALL-CAPS —
SCHEMA.md,README.md,INDEX.md.
Front-Matter Format
Every entity page begins with a YAML front-matter block — the page’s machine-readable contract.
Wiki-only convention. This front-matter shape is adopted only in
wiki/. The operator runbooks undercontent/carry their own Hugo front-matter; governance docs (docs/PLAN.md,docs/01-REPO-FOLDER-STRUCTURE.md) use the# Title+> **Last updated:**header pattern.
---
title: SSH Hardening
type: Tutorial
tags: [foundations, security, ssh, ubuntu]
related:
- provision-droplet.md
- ufw-firewall.md
status: draft
source:
- C:\www\legendary-arena-lab\wiki\ssh-hardening.md (this page — internal operator wiki)
- ../infra/scripts/05-user-and-ssh.ps1
- ../docs/PLAN.md
- ../content/foundations/ssh-hardening.md
last-reviewed: 2026-07-24
---
Field reference
| Field | Required | Type | Notes |
|---|---|---|---|
title | yes | string | Human-readable title. |
type | yes | enum | One of the closed set below. |
tags | yes | list of strings | Lowercase-hyphenated. Free vocabulary. [] permitted but discouraged. |
related | yes | list of relative paths | Other wiki pages this entity touches. May be [] for true leaf entities. |
status | yes | enum | canonical | draft | deprecated |
source | conditional | list | First entry is the page’s own self-reference. Remaining entries are the authoritative artifacts cited, as relative paths. Non-empty for canonical. |
last-reviewed | yes | date YYYY-MM-DD | When the page was last verified against current artifacts. |
Self-reference (first source entry)
The first entry in source is the page itself — its full drafting
path — so a reader can tell from the file which copy is authoritative:
source:
- C:\www\legendary-arena-lab\wiki\<slug>.md (this page — internal operator wiki)
There is no published URL locked yet (the plan puts the rendered operator wiki on Hugo behind Cloudflare Access — see PLAN.md §1 ); update the self-reference when a URL exists.
Required Sections
Every entity page must contain these H2 sections, in this order:
## Summary— One to three sentences. What this entity is and why it matters in the migration. No code, no citations.## Mechanics— How it actually works: what the owning artifact does, the key config values, the order of operations. Concrete, technical, citable.## Interactions— Which other entities this one touches, and how. Each interaction names another wiki page (link to it) or a specific artifact with a citation.## Edge Cases— Corner conditions, lockout hazards, cutover gotchas, and drift risks. If none are known, writeNone known at this revision.rather than omitting the section.## References— Bullet list of cited artifacts. May overlap with front-mattersourcebut is the human-readable rendering.
Section names are fixed. Do not rename Mechanics to How it works
or Edge Cases to Gotchas.
Optional Sections
These may appear when relevant, after Edge Cases and before References:
## Execute— The exact command(s) to run the owning script, including documented environment-variable overrides. Use forTutorialpages whose entity is a runnable script.## Verify— Commands that confirm the entity is in the desired state, with expected output.## Code Touchpoints— Relevant repo paths with one-line descriptions.## History— Timeline of plan phases / decisions that introduced or changed this entity.## Open Questions— Gaps the page could not fill from authoritative sources. Pages with open questions usually havestatus: draft.
Entity Types (Closed Set)
type must be exactly one of:
| Type | Definition | Examples |
|---|---|---|
Tutorial | A step-by-step procedure that runs an owning infra artifact | SSH Hardening, Nginx Reverse Proxy, PostgreSQL Setup |
Guide | A reference explaining conventions, contracts, or a subsystem without a single runnable script | Secrets and Env, Systemd Service |
Concept | An abstract idea, contract, or design decision | Render-to-DigitalOcean Migration, Idempotent Provisioning |
Reference | A standing lookup — costs, ownership boundaries, tables | Cost and Ownership |
This set is closed. Adding a new type requires updating SCHEMA.md first.
Status Values (Closed Set)
| Status | Meaning | Constraints |
|---|---|---|
canonical | Every claim is sourced; verified against current artifacts at last-reviewed. | source is non-empty; no uncited factual claims in body. |
draft | Exists but has uncited claims, content gaps, or pending real-host verification (the migration has not executed against a live droplet yet). | source may be []. Open Questions recommended. |
deprecated | Superseded or no longer accurate. Kept for history. | Page links to its replacement in the first paragraph of Summary. |
Pre-execution note. At the current phase, the
infra/scripts and configs exist and are described accurately, but the migration has not been run against a production host. Pages that describe on-host outcomes therefore carrystatus: draftuntil verified on a real droplet, even when every claim cites an existing artifact. This is honest scope, not incompleteness.
Cross-Reference Conventions
Within the wiki
See [SSH Hardening](ssh-hardening.md) for the access-hardening sequence.
To repo artifacts outside the wiki
Paths are relative to the current page (wiki/<slug>.md), so up one
level (../) is the repo root:
- [PLAN.md §1](../docs/PLAN.md)
- [infra/scripts/06-ufw.ps1](../infra/scripts/06-ufw.ps1)
- [infra/nginx/api.conf](../infra/nginx/api.conf)
- [content/foundations/ufw-firewall.md](../content/foundations/ufw-firewall.md)
Forbidden link styles
- No Obsidian wiki-links —
[[SSH Hardening]]does not render in plain markdown. - No bare URLs in body text — every link has visible link text.
- No absolute paths in body links —
C:\...breaks across machines. (Thesourceself-reference is the one deliberate exception, per the reference-wiki convention it inherits.)
Link integrity
Every internal link — within the wiki or out to a repo artifact —
must resolve to an existing file. Broken internal links are review
failures. Do not link to scripts that do not yet exist (e.g. the
planned 50-backup.ps1); mention them in prose as planned instead.
Source Field Conventions
What counts as an authoritative source
- Governance:
.claude/CLAUDE.md,docs/PLAN.md,docs/01-REPO-FOLDER-STRUCTURE.md - Executable artifacts:
infra/scripts/*.ps1,infra/cloud-init.yaml,infra/nginx/*.conf,infra/systemd/*.service,infra/.env.example,.github/workflows/*.yml - Operator runbooks:
content/**/*.md
What does NOT count
- This wiki itself (it cannot bootstrap its own authority)
- Conversation transcripts or scratch notes
- Commit messages alone (cite the plan phase or artifact the commit landed under)
Citation precision
- Cite the specific script or config file an entity owns.
- Cite PLAN.md section anchors when describing a locked decision.
- For scripts, cite the file; do not cite line numbers — they rot.
When to Add a Page
Add a wiki page when an entity:
- Has an owning infra artifact or a named subsystem in this repo, and
- Has non-trivial mechanics worth explaining beyond the runbook’s step list, and
- Is referenced by other entities (it’s an anchor, not a leaf).
Do not add a page for:
- A script that does not yet exist in
infra/ - One-off implementation details better left as a code comment
- Decisions — those live in PLAN.md
Maintenance
- Update
last-reviewedwhenever the page is verified against the current artifact (not on every typo fix). - Promote
draft→canonicalonly when every body claim is cited and the described behaviour has been verified on a real host. - When a plan phase or script changes an entity, update the page’s
HistoryandReferencesin the same change. - Regenerate INDEX.md
when a page is added, renamed, or has
its
type/statuschanged.
Reserved Filenames
| File | Purpose |
|---|---|
SCHEMA.md | This file — the contract. |
README.md | Purpose, conventions, authority hierarchy. |
INDEX.md | Categorized list of every page in the wiki. |
These filenames are reserved and must not be used as entity slugs.