184 lines
9.4 KiB
Markdown
184 lines
9.4 KiB
Markdown
# Milestone 13: restructure the documentation to Diátaxis
|
|
|
|
Goal: replace the four mixed-mode documents with the four Diátaxis modes, add the
|
|
missing tutorial, and prove every instruction by running it.
|
|
|
|
## Rulings (binding)
|
|
|
|
1. **Four directories plus an index.** `docs/tutorial/`, `docs/how-to/`,
|
|
`docs/reference/`, `docs/explanation/`, and `docs/README.md` — the index names
|
|
the four modes, says who each is for, and links every page. The old
|
|
`docs/{operator,architecture,config-reference,api,performance}.md` are deleted
|
|
by the orchestrator once the new pages exist; no redirect stubs (greenfield
|
|
repo, AGENTS.md forbids compatibility leftovers).
|
|
|
|
2. **A document serves one mode.** The defect being fixed is `operator.md`, which
|
|
interleaves install procedure, CLI reference, exit-code tables and
|
|
troubleshooting in 418 lines. Reference pages state what is; how-to pages state
|
|
what to do; explanation states why; the tutorial teaches. When porting text,
|
|
move a paragraph to the mode it belongs to rather than keeping it where it was.
|
|
|
|
3. **Every command block in `tutorial/` and `how-to/` is executed verbatim by the
|
|
session that writes it**, on this host, before the session reports. A command
|
|
that cannot run here (needs a Raspberry Pi, root, a domain, hardware TLS) is
|
|
marked in the page itself as not verified on this host, with the reason. This
|
|
ruling exists because milestone 11's docs were written from source-reading
|
|
alone: the first real blocklist download aborted the process (commit 35f2324)
|
|
and a stale SPA bundle crashed the settings page — both would have surfaced if
|
|
the documented paths had been run. No session may report a page complete on the
|
|
strength of having read the code.
|
|
|
|
4. **Content is verified against `src/`, not copied from the old pages.** Defaults,
|
|
flags, exit codes, paths and route names come from the code at HEAD. Report any
|
|
discrepancy found; do not fix source in this milestone (docs-only, ruling 9).
|
|
|
|
5. **The tutorial has one guaranteed outcome.** `docs/tutorial/first-run.md` takes
|
|
a reader from a clean checkout to a running nxdns that answers a query and
|
|
blocks a domain from a real blocklist, on unprivileged ports in a scratch
|
|
directory, then stops it cleanly. It teaches by doing and states what the reader
|
|
will have at the end. No branching, no options menu, no "you may also".
|
|
|
|
6. **File map.**
|
|
- `docs/tutorial/first-run.md` — new.
|
|
- `docs/how-to/`: `install-with-systemd.md` (incl. the Raspberry Pi 5 aarch64
|
|
binary), `install-with-docker.md`, `upgrade.md`, `troubleshoot.md`,
|
|
`enable-doh-and-dot.md`, `set-up-admin-authentication.md`,
|
|
`back-up-and-restore.md`, `measure-performance.md`.
|
|
- `docs/reference/`: `configuration.md` (every section, field, default, range),
|
|
`api.md` (all 56 operations), `cli.md` (six subcommands, every flag, exit
|
|
codes), `files-and-directories.md` (data dir layout, file modes),
|
|
`performance.md` (targets + measured numbers).
|
|
- `docs/explanation/`: `architecture.md`, `configuration-model.md` (the file
|
|
seeds the database once, the database is truth, export/import round trip),
|
|
`performance-and-testing.md` (why the targets exist, why CI does not gate on
|
|
them, what hermetic tests do and do not prove).
|
|
|
|
7. **Drift guards repointed and kept honest.** `docs/docs.zig` embeds
|
|
`reference/api.md`, `reference/configuration.md`, `reference/cli.md`.
|
|
`src/docs_drift_test.zig` keeps its three guards against those paths: every
|
|
served route as a full `| METHOD | \`pattern\` |` row; every `toSettings` key
|
|
verbatim; every subcommand as its own heading. `reference/cli.md` gives each
|
|
subcommand a `## \`name\`` heading so the guard anchors on structure, not prose.
|
|
|
|
8. **Style.** Plain sentences. No banned vocabulary (leverage, seamless, robust as
|
|
filler, rule-of-three padding, "it's important to note"). No badges, no
|
|
marketing. Code blocks are copy-pasteable and use the scratch paths the
|
|
tutorial establishes, not `/var/lib/nxdns`, unless the page is about a real
|
|
install.
|
|
|
|
9. **Docs-only.** The only non-docs edits are the orchestrator's: `docs/docs.zig`,
|
|
`src/docs_drift_test.zig`, `README.md` links, and PLAN.md's repo-layout line.
|
|
No behavior changes.
|
|
|
|
## Sessions
|
|
|
|
X1, X2, X3, X4, X5 run in parallel — every session owns distinct files.
|
|
|
|
## Session X1: index + tutorial + README links
|
|
|
|
Owns `docs/README.md`, `docs/tutorial/first-run.md`, `README.md` (links section
|
|
only). Rulings 1, 5, 3 (the tutorial is executed end to end).
|
|
|
|
## Session X2: how-to, install and operations
|
|
|
|
Owns `docs/how-to/{install-with-systemd,install-with-docker,upgrade,troubleshoot}.md`.
|
|
Rulings 2, 3, 4.
|
|
|
|
## Session X3: how-to, security and measurement
|
|
|
|
Owns `docs/how-to/{enable-doh-and-dot,set-up-admin-authentication,back-up-and-restore,measure-performance}.md`.
|
|
Rulings 2, 3, 4.
|
|
|
|
## Session X4: reference
|
|
|
|
Owns `docs/reference/{configuration,api,cli,files-and-directories,performance}.md`.
|
|
Rulings 2, 4, 7 (heading convention).
|
|
|
|
## Session X5: explanation
|
|
|
|
Owns `docs/explanation/{architecture,configuration-model,performance-and-testing}.md`.
|
|
Rulings 2, 4.
|
|
|
|
## File ownership
|
|
|
|
X1 docs/README.md + docs/tutorial/* + README.md; X2 and X3 disjoint files under
|
|
docs/how-to/; X4 docs/reference/*; X5 docs/explanation/*. Orchestrator:
|
|
docs/docs.zig, src/docs_drift_test.zig, PLAN.md, deletion of the old pages, spec.
|
|
|
|
## Delivered
|
|
|
|
Seventeen pages: `docs/README.md`, one tutorial, eight how-to guides, five
|
|
reference pages, three explanation pages. The five old documents are deleted.
|
|
|
|
The orchestrator repointed `docs/docs.zig` at `reference/{api,configuration,cli}.md`
|
|
and `src/docs_drift_test.zig` at the same three, moved the subcommand anchor from
|
|
`### \`name` to `## \`name`, fixed the README Quickstart link that pointed at the
|
|
deleted `operator.md`, and corrected PLAN.md's repo-layout line and its §13.2
|
|
OpenAPI paragraph (which still promised a renderer and contract tests that were
|
|
never built).
|
|
|
|
All three guards were proven able to fail: deleting one API table row, one
|
|
settings key row and one `## \`export` heading each produced a named build
|
|
failure. The settings guard was strengthened during review — it searched for a
|
|
bare key, which prose and the annotated example could satisfy after a field's row
|
|
was deleted; it now anchors on `| \`key\` |`.
|
|
|
|
Ruling 3 held. The tutorial ran end to end twice, the second time after the review
|
|
fixes. DoH and DoT answered real queries, `POST /api/certs/reload` returned both
|
|
its success and its failure payload, the export/import round trip was
|
|
byte-identical, a Docker image was built and its container served DNS, and the
|
|
offline password change was proven (old password 401, new 200). What could not run
|
|
here — root-only steps, a second LAN host, a Raspberry Pi, a registry push, the
|
|
full-scale bench, `dnsperf` — is marked in the page that documents it, with the
|
|
reason.
|
|
|
|
Five review rounds: 15 findings, then 8, then 1, then 1, then clean. One round-1
|
|
finding was rejected on evidence (`troubleshoot.md` already stated the verified
|
|
exit codes; the contradiction was in `reference/cli.md`).
|
|
|
|
## Discrepancies found, not fixed
|
|
|
|
Docs-only per ruling 9. These are source-side and belong to a later milestone:
|
|
|
|
1. `nxdns run` exits 1 for seed-file errors (`ParseZon`, `MissingDefaultGroup`,
|
|
`NoUpstreams`) while `check` and `import` exit 2 for the same file, because
|
|
`app.isConfigFault` lists only `NoUsableUpstreams`, `BadBindAddress`,
|
|
`BadRateLimit`, `BadCertificate`.
|
|
2. `nxdns check` prints `OK: no problems found` and exits 0 after emitting WARN
|
|
lines.
|
|
3. `nxdns check` never parses a certificate or tests that the key matches it — it
|
|
checks path readability and key mode only. A green `check` is followed by
|
|
`run` exiting 2 with `BadCertificate` on a mismatched pair.
|
|
4. `check --config <missing file>` exits 1; the implicit path prints `nothing to
|
|
check` and exits 2.
|
|
5. A blocklist source attached to no group is silently inert, and `validate.zig`
|
|
has no diagnostic for it.
|
|
6. `nxdns check` says it validates without writing, but the `config.db` branch
|
|
chmods, enables WAL and runs migrations.
|
|
7. `pruneOrphans` matches only `.list`/`.wild`, so an orphaned `.raw.tmp` is never
|
|
swept.
|
|
8. `isEmpty` counts auto-materialised client rows, so a server that has answered
|
|
one query ignores a seed file placed afterwards.
|
|
9. PLAN §18 and the docs say 10 MB / 15 MB; CI asserts 10 MiB / 15 MiB.
|
|
|
|
## Acceptance (milestone complete)
|
|
|
|
- [x] The five old `docs/*.md` files are gone; the four directories and the index
|
|
exist with every page in ruling 6.
|
|
- [x] Every command in `tutorial/` and `how-to/` was executed on this host, or is
|
|
marked in-page as unverified with a reason.
|
|
- [x] `zig build test` passes with the three drift guards pointing at the new
|
|
reference pages: 16/16 steps, 1175 pass, 113 skip (integration-gated), 0 failed.
|
|
- [x] `zig build test -Dintegration` passes: 1284 pass, 4 skip (the live-network
|
|
TLS tests excluded by milestone-1 design), 0 failed. No src/ behavior change.
|
|
- [x] No page mixes modes: no procedure in `reference/`, no field table in any
|
|
`how-to/` or `tutorial/` page.
|
|
|
|
## Anti-requirements
|
|
|
|
- No new documentation subjects (no metrics-families reference, no security-model
|
|
page) — this milestone moves and splits existing content plus the tutorial.
|
|
- No redirect stubs or `docs/legacy/`.
|
|
- No source fixes; report discrepancies instead.
|
|
- No doc generator, no site builder, no MkDocs.
|