Files
photoanalyzer/delivery_backlog/stories/US09-01-docs-in-app.md
domverse 792134c72d
Some checks failed
Test / suites (pull_request) Failing after 3m27s
Test / container (pull_request) Has been skipped
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015csGY8XV1M92fHfKnMmjtu
2026-08-23 15:03:55 +02:00

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 /docs view 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 mermaid fenced blocks render as diagrams. Mermaid is vendored the same way.
  • script-src in the Content-Security-Policy is unchanged: no 'unsafe-eval', no 'unsafe-inline'. Only style-src gains 'unsafe-inline', and the reason is recorded where the policy is defined.
  • Links between documents work in the app: a relative ../foo.md#section link 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.