From 792134c72dde02997eb0e997782bec36d9d790ab Mon Sep 17 00:00:00 2001 From: domverse Date: Sun, 23 Aug 2026 15:03:55 +0200 Subject: [PATCH] docs: add E09, the product documentation epic Adds the installation manual, architecture overview, and illustrated user manual as a five-story epic, plus the acceptance gate that keeps them true. The documentation is markdown under docs/, so the same files are readable in the repository and rendered by the deployed application at /app/#/docs. An operator who was handed a URL and an access secret has no repository checkout in front of them, and the network the application is deployed to is not assumed to reach a CDN. Two decisions are recorded in the epic rather than left to implementation: - The renderer is vendored (marked), not written and not fetched. - Diagrams are mermaid, rendered client-side, with script-src untouched. Whether mermaid needs 'unsafe-eval' was measured rather than assumed: its bundle contains no eval( and no new Function, and rendered under this application's exact CSP it produced an SVG with no script-src violation. What it does violate is style-src, which gains 'unsafe-inline'. With script-src, img-src, connect-src, and font-src all unchanged, that leaves defacement rather than execution or exfiltration. The alternative -- pre-rendering diagrams to committed SVG with the already-installed Playwright -- is recorded as the migration if that trade is ever refused. Screenshots are generated from the running application, never pasted, and every documented setting, command, exit code, error code, and state is cross-checked against the code that implements it, so stale documentation fails a test instead of misleading an operator. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_015csGY8XV1M92fHfKnMmjtu --- delivery_backlog/E09-documentation.md | 77 +++++++++++++++++++ delivery_backlog/README.md | 10 ++- .../stories/US09-01-docs-in-app.md | 49 ++++++++++++ .../stories/US09-02-installation-manual.md | 46 +++++++++++ .../stories/US09-03-architecture-overview.md | 47 +++++++++++ .../stories/US09-04-user-manual.md | 52 +++++++++++++ delivery_backlog/stories/US09-05-docs-gate.md | 38 +++++++++ tests/story_traceability.json | 8 +- 8 files changed, 322 insertions(+), 5 deletions(-) create mode 100644 delivery_backlog/E09-documentation.md create mode 100644 delivery_backlog/stories/US09-01-docs-in-app.md create mode 100644 delivery_backlog/stories/US09-02-installation-manual.md create mode 100644 delivery_backlog/stories/US09-03-architecture-overview.md create mode 100644 delivery_backlog/stories/US09-04-user-manual.md create mode 100644 delivery_backlog/stories/US09-05-docs-gate.md diff --git a/delivery_backlog/E09-documentation.md b/delivery_backlog/E09-documentation.md new file mode 100644 index 0000000..d2c2cad --- /dev/null +++ b/delivery_backlog/E09-documentation.md @@ -0,0 +1,77 @@ +# 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 `