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.4 KiB
2.4 KiB
US09-03 — Write the Architecture Overview
Epic: E09
As a developer or reviewer new to this repository, I want an architecture overview that explains what the pieces are and which rules they enforce, so that I can find the right module and not violate an invariant I never knew existed.
Acceptance criteria
- A context diagram: the operator, the browser application, the API and worker, the photo library, the Immich server, the vision provider, and the archive destination — with the direction and nature of every interaction, including which ones leave the machine.
- A runtime diagram: the migrate/api/worker composition, the data volume, the library bind mount, the SQLite database, and the process lock — showing what is shared and what is exclusive.
- A module map: every package under
photo_pipeline/with its responsibility and the boundary it must not cross (which modules may touch the filesystem, which may call an external provider, which own schema). - Key flows, each as a diagram plus prose: the durable job lifecycle from enqueue to recovery; the rename journal state machine including the rollback and manual-resolution paths; the upload lifecycle through preflight, run, report ingestion, and verification.
- The invariants and where they are enforced, each pointing at the module that owns
it: one writer at a time, the library process lock, the path policy and library roots,
_IGNORE/exclusion, verified EXIF before upload, safety decisions gating the vision provider, and restart-safety of every mutation. - The data model: the tables, what identity means for an asset, and how a moved file keeps its identity.
- A short history and donor section: what was migrated out of the legacy CLIs, where the archive and its ledger live, and why they are kept.
- Diagrams are
mermaidblocks so the source is diffable and Gitea renders them natively.
Automated tests
- Every package and top-level module under
photo_pipeline/appears in the module map, and every module named in the map exists — a new service cannot appear on the map's blind side. - Every job state, journal state, and upload batch state named in the document exists in the code, and every state the code defines is named in the document.
- Every mermaid block parses (rendered in the browser test without an error node).
- Every code path referenced by file name exists.
Dependencies
- US09-01