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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015csGY8XV1M92fHfKnMmjtu
2.7 KiB
2.7 KiB
US09-01 — Serve the Documentation Inside the Application
Epic: E09
As an operator who was handed a URL and an access secret, I want the manuals inside the application I am looking at, so that understanding it does not require a repository checkout or an internet connection.
Acceptance criteria
- Documentation lives as markdown under
docs/, with an index that names every page and the order it is meant to be read in. The same files render on Gitea without modification. - The application serves a
/docsview reachable from the main navigation, listing the pages and rendering the selected one. - Rendering uses a vendored, version-pinned markdown library committed under
frontend/js/vendor/. It is not fetched from a CDN, not bundled by a build step, and not written by hand. The build records the version and a checksum of the vendored file. - Diagrams written as
mermaidfenced blocks render as diagrams. Mermaid is vendored the same way. script-srcin the Content-Security-Policy is unchanged: no'unsafe-eval', no'unsafe-inline'. Onlystyle-srcgains'unsafe-inline', and the reason is recorded where the policy is defined.- Links between documents work in the app: a relative
../foo.md#sectionlink navigates to that page and heading rather than downloading a file or leaving the application. Every heading has a stable anchor, and a deep link to an anchor scrolls to it. - An unknown page renders a documentation-specific not-found message with a link back to the index, and never exposes a filesystem path.
- Documentation is readable without an access secret or behind the same session as the rest of the application — whichever is chosen is stated explicitly in the story's implementation notes and covered by a test, because an operator locked out by a configuration mistake is exactly who needs the troubleshooting page.
- The view works with no outbound network access at all.
Automated tests
- Unit: heading-anchor slugs (duplicates, punctuation, non-ASCII), and the rewriting of relative markdown links into in-app routes.
- Integration: every markdown file under
docs/is reachable from the index; every internal link in every document resolves to a file and, where an anchor is given, to a heading that exists; the vendored library files match their recorded checksums. - Browser: the documentation view renders a page, follows an internal link, deep-links to an anchor, renders a mermaid diagram to an SVG, and shows the not-found message for an unknown page — all with zero console errors and zero CSP violations, asserted, not eyeballed.
Dependencies
- None beyond the delivered application.