78 lines
4.5 KiB
Markdown
78 lines
4.5 KiB
Markdown
# E09 — Product Documentation
|
|
|
|
Concept phase: none. Like [E08](E08-container-deployment.md), this epic is a delivery
|
|
addition rather than a product-scope change: the same application, documented well
|
|
enough that somebody who did not build it can install it, understand it, and operate it
|
|
without reading the source.
|
|
|
|
It does not change the product scope in
|
|
[`INTEGRATED_PIPELINE_CONCEPT.md`](../INTEGRATED_PIPELINE_CONCEPT.md). No safety
|
|
invariant moves, no schema changes, no new runtime capability. The one change to the
|
|
running application is a documentation view and the static assets it needs.
|
|
|
|
## Why the application serves its own documentation
|
|
|
|
The manuals describe an application that is reached over HTTP behind an access secret.
|
|
Documentation that lives only in the repository is unreachable from the deployment it
|
|
describes: an operator who has just been handed a URL and a secret has no Gitea account
|
|
in front of them. So the same markdown files are both the repository's documentation and
|
|
the deployment's `/docs` view, and neither is a copy of the other.
|
|
|
|
## Decisions made in this epic
|
|
|
|
**Markdown is the source.** Everything is written as markdown under `docs/`, so it is
|
|
reviewable in a diff, readable on Gitea, and renderable in the app. No documentation
|
|
format that only a tool can read.
|
|
|
|
**The renderer is vendored, not written and not fetched.** `marked` (MIT, no
|
|
dependencies, ships an ES module) is pinned and committed under
|
|
`frontend/js/vendor/`. A CDN is not an option: the application is deployed to a network
|
|
whose outbound access is not assumed, and `default-src 'self'` forbids it.
|
|
|
|
**Diagrams are mermaid, rendered client-side, with the script boundary intact.** The
|
|
claim that mermaid requires `'unsafe-eval'` was tested rather than believed: mermaid 11's
|
|
bundle contains no `eval(` and no `new Function` — only a lodash `Function("return this")`
|
|
global-detection fallback that short-circuits on `globalThis` and never executes.
|
|
Rendered under this application's exact CSP, a flowchart produced a 15.8 KB SVG and
|
|
raised **no `script-src` violation**. What it does raise is `style-src`: mermaid styles
|
|
its output with an injected `<style>` element and `style=` attributes.
|
|
|
|
So `script-src 'self'` stays exactly as US07-02 and US08-01 left it, and `style-src`
|
|
gains `'unsafe-inline'`. That relaxation is bounded on purpose: with `script-src` intact
|
|
no injected markup can execute, and with `img-src`, `connect-src`, and `font-src` all
|
|
still `'self'`, the CSS-based exfiltration channels stay closed. What remains is
|
|
defacement of a page the operator is already authenticated on.
|
|
|
|
The rejected alternative is recorded because it may become the better trade later:
|
|
pre-rendering each diagram to a committed SVG with the already-installed Playwright
|
|
(no Node toolchain needed) and serving that, which would leave CSP untouched entirely at
|
|
the cost of a generator and a freshness check. If `style-src 'unsafe-inline'` is ever
|
|
judged too much, that is the migration, and it does not change a single markdown file.
|
|
|
|
**Screenshots are produced, not pasted.** Every screenshot in the user manual is captured
|
|
by Playwright from the real application against a temporary fixture library, by the same
|
|
kind of code that already drives the browser suites. A screenshot nobody can regenerate
|
|
is a screenshot that silently stops being true.
|
|
|
|
**The documentation is held to the code by tests.** Configuration keys, CLI commands,
|
|
exit codes, API error codes, job and journal states, and module names all appear in both
|
|
the code and the manuals. Each of those is cross-checked, so the failure mode of stale
|
|
documentation is a red test rather than a misled operator.
|
|
|
|
## Stories
|
|
|
|
1. [US09-01 — Serve the documentation inside the application](stories/US09-01-docs-in-app.md)
|
|
2. [US09-02 — Write the installation and operations manual](stories/US09-02-installation-manual.md)
|
|
3. [US09-03 — Write the architecture overview](stories/US09-03-architecture-overview.md)
|
|
4. [US09-04 — Write the user manual with generated screenshots](stories/US09-04-user-manual.md)
|
|
5. [US09-05 — Automate documentation acceptance](stories/US09-05-docs-gate.md)
|
|
|
|
## Epic outcome
|
|
|
|
A deployed instance serves its own installation manual, architecture overview, and
|
|
illustrated user manual at `/app/#/docs`, rendered from the same markdown files that are
|
|
readable in the repository. Screenshots are regenerated from the running application,
|
|
every documented command, setting, state, and error code is cross-checked against the
|
|
code that implements it, and one gate fails the build when documentation and application
|
|
disagree.
|