epic(legibility): documentation — make the codebase self-explaining #394
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Epic context
This is Epic 2 of 5 for the Codebase Legibility Refactor (see #387 for the meta-context). The goal of this epic is to replace LLM-targeted
CLAUDE.mdcontent with human-targeted documentation that lets Anja, Tobias, or any future Successor-X form a correct mental model fromdocs/and code-adjacent READMEs alone, without the original author present.This epic can run in parallel with Epic 1 (Audit) and before Epic 4 (Refactor) — docs are written against the target domain structure, not the current one.
Scope
Seven focused documentation tasks:
README.md(front door)docs/ARCHITECTURE.mdwith diagram and domain listdocs/GLOSSARY.mdfor overloaded terms (Person ≠ AppUser, etc.)CONTRIBUTING.mdwith three concrete walkthroughs (add a domain / endpoint / page)docs/DEPLOYMENT.md(production runtime + env vars + log locations)README.mdinside each domain package (~14 files across both stacks)CLAUDE.mdfiles into the human docs above; mark migrated content in CLAUDE.md as movedInputs
docs/audits/(when available — DOC-* tasks should reference findings if Epic 1 has produced them)CLAUDE.mdfiles at repo root,frontend/,backend/,ocr-service/,docs/,scripts/,.devcontainer/— these contain valuable knowledge that needs migration, not rewriting from scratchAcceptance criteria
README.md(root) is human-targeted, lists 5 subsystems, links to local-run / contribute / issues (DOC-1)docs/ARCHITECTURE.mdcontains a diagram and names every canonical domain (DOC-2)docs/GLOSSARY.mddisambiguates every overloaded term in the system (DOC-3)CONTRIBUTING.mdcontains the three walkthroughs (DOC-4)docs/DEPLOYMENT.mdcovers all production runtime concerns (DOC-5)README.mdon both stacks (DOC-6)Definition of Done
This epic closes when DOC-1 through DOC-7 are all closed AND the rubric checks above are verified PASS in a subsequent audit re-run (CLEANUP-5 in Epic 5 will do this).
🏗️ Markus Keller — Senior Application Architect
Observations
docs/adr/001–006) but the rootCLAUDE.mdandbackend/CLAUDE.mddon't link to them. DOC-2 (ARCHITECTURE.md) is the right place to surface them prominently — not just as a file list but with a one-liner on each decision's consequence.docs/architecture/c4-diagrams.mdcover Levels 1–3 but the existing diagram pre-dates several subsystems now visible in the codebase:OcrService,GeschichteService,TranscriptionQueueService,SseEmitterRegistry,NotificationService. DOC-2 must refresh these or the diagram is misleading.SenderModel,Geschichte(not a standard German archive term),TranscriptionBlockvsDocumentVersion,OcrJobvsOcrBatchServicevsOcrAsyncRunner. Each of these creates a mental-model gap for a newcomer.controller/,service/,repository/,model/,dto/,exception/,security/,config/— but the actual codebase also hasaudit/,dashboard/,relationship/. DOC-2 and the backend domain READMEs (DOC-6) must document actual structure, not the wishlist from CLAUDE.md.Tagas the example: it has a controller, service, repository, migration, and frontend component all small enough to read in one sitting.Recommendations
GeschichteServiceandTranscriptionQueueServiceas they represent significant domain areas not in the original diagram.backend/CLAUDE.md— Flyway naming convention, layering rules,@Transactionalpolicy — belong inCONTRIBUTING.mdDOC-4, not in a separate doc. Migrate them there rather than creating a fourth location.audit/,dashboard/,relationship/exist) so newcomers don't hit the first contradiction on day one.👨💻 Felix Brandt — Senior Fullstack Developer
Observations
backend/,frontend/,frontend/e2e/,ocr-service/,docs/,scripts/,.devcontainer/,infra/,import/. That's 10 files. Many contain actionable implementation rules (e.g., frontend CLAUDE.md documents thePersonTypeahead,PersonMultiSelect,TagInputcomponent APIs and the$derived/$effectguidance). These rules need to survive migration intact — they are currently the most reliable source of "how to do X in this codebase."docs/STYLEGUIDE.mdalready exists and overlaps with what DOC-4's code-style content would contain. Before writing CONTRIBUTING.md, check what's in STYLEGUIDE.md to avoid a third source of truth for the same rules.frontend/CLAUDE.mddocumentsbriefwechsel/but calling it/conversations/in the root CLAUDE.md. The route is actuallybriefwechsel/(confirmed via CLAUDE.md frontmatter). DOC-1 and CONTRIBUTING.md must use the actual route names.Recommendations
+page.server.tsload → typedcreateApiClientcall →!result.response.okguard →+page.sveltewith$props()→ error state. This is the pattern every frontend change follows.src/lib/components/subdirectories (document/,chronik/,user/) not just at the package level, since that's where a newcomer lands when following an import path.docs/STYLEGUIDE.mdbefore drafting DOC-4 — migrate its non-duplicated content, then either archive it or replace it with a pointer to CONTRIBUTING.md. Three style-guide sources are worse than one.🔒 Nora "NullX" Steiner — Application Security Engineer
Observations
backend/CLAUDE.mdand the root CLAUDE.md give no guidance on which environment variables contain secrets, what their expected formats are, or what happens if they're missing. A newcomer setting up the stack will cargo-cult from.env.exampleand may accidentally use dev defaults in production. The doc needs a "non-negotiable before going live" checklist.ocr-service/CLAUDE.mdexists but the root CLAUDE.md doesn't describe the OCR service's auth model (X-Training-Tokenheader for the training endpoint). DOC-5 or a dedicated OCR service README (DOC-6) must document: which OCR endpoints are unauthenticated, which require the training token, and where that token must be set.Permissionenum values.READ_ALL,WRITE_ALL,ADMIN,ADMIN_USER,ADMIN_TAG,ADMIN_PERMISSIONare opaque to someone reading the codebase for the first time. What doesADMINgrant vsADMIN_USER? The security model's mental map belongs in the glossary or a dedicated security section of ARCHITECTURE.md.docs/security-guide.mdalready exists at the repo root. DOC-5 or DOC-2 should link to it rather than duplicating production security concerns. But the security guide must itself be reviewed as part of DOC-7 — it may contain stale CLAUDE.md-style guidance that needs migration.Recommendations
@RequirePermission+PermissionAspectmechanism and the permission hierarchy. Anja needs to know this before she can safely add a new endpoint.scripts/CLAUDE.mdandinfra/CLAUDE.mdfor any hardcoded test credentials or dev secrets that have drifted into those files. Migrate the legitimate content; delete the sensitive bits from the committed history if any exist.🧪 Sara Holt — Senior QA Engineer
Observations
@WebMvcTestslices, Testcontainers integration, Playwright E2E) is not documented in any of the seven planned docs. DOC-4 (CONTRIBUTING.md) is the natural home.docs/infrastructure/ci-gitea.md, but it's unclear whether that document covers test execution order, quality gates, or what blocks a merge. A newcomer won't know to look there for test strategy.docs/audits/doesn't exist yet (confirmed byls). DOC-* tasks reference audit findings as inputs — but Epic 1 (Audit) may not complete before or alongside this epic. The acceptance criteria for DOC-2/DOC-3 that say "reference findings if Epic 1 has produced them" will need a fallback — what does a complete DOC-2 look like if no audit findings are available?Recommendations
./mvnw test,npm run test,npm run test:e2e), what quality gates exist, and the TDD expectation (red/green/refactor). This is the single most important thing a contributor needs after understanding architecture.frontend/e2e/.auth/user.jsonstores authenticated state. A newcomer running Playwright without this setup gets confusing failures. Explain how to regenerate it (npm run test:e2e -- --headed).frontend/e2e/CLAUDE.md: The e2e CLAUDE.md likely contains test-running instructions and seed-data expectations. These should migrate to DOC-4 rather than being marked "LLM-only."🎨 Leonie Voss — UX Designer & Accessibility Strategist
Observations
docker-compose.yml,CLAUDE.md,CODESTYLE.md,COLLABORATING.md,CODESTYLE.md(duplicate in git status). The README needs to answer "what is this, how do I run it, and where do I go next" within the first 20 lines.docs/STYLEGUIDE.mdexists butdocs/CLAUDE.mdalso exists. From Tobias's perspective (PM-with-CS), two docs-about-docs create confusion about where to look for design/style decisions. DOC-7 should resolve this by establishing a clear single location.Recommendations
CONTRIBUTING.md, (2) "I want to understand the system" → points todocs/ARCHITECTURE.md, (3) "I want to contribute" → points toCONTRIBUTING.md. Three journeys, three paragraphs, done.## Walkthrough: Add a New Domain,## Walkthrough: Add an API Endpoint,## Walkthrough: Add a SvelteKit Route) so they appear in the GitHub/Gitea table of contents and can be linked to directly.🖥️ Tobias Wendt — DevOps & Platform Engineer
Observations
docs/infrastructure/already has all four files (ci-gitea.md,production-compose.md,s3-migration.md,self-hosted-catalogue.md). DOC-5 (DEPLOYMENT.md) risks creating a fifth overlapping source. The better approach is DOC-5 as a single-page entry point that links into the existing infrastructure docs rather than duplicating them.infra/CLAUDE.mdexists (untracked in git status). Its content needs to be reviewed as part of DOC-7 — it may contain production-relevant infrastructure rules that belong indocs/infrastructure/production-compose.mdrather than a CLAUDE.md.ocr-service/Dockerfileandocr-service/CLAUDE.mdexist, but the root CLAUDE.md describes onlydocker-compose up -dfor the three core services (PostgreSQL, MinIO, Spring Boot). The OCR service — which has an 8GB memory limit, a 60-second startup due to model loading, and a training token requirement — is invisible in the current developer-facing documentation.scripts/directory hasclean-e2e-data.sh,download-paperless.sh,flatten-paperless.sh,reset-db.sh,scripts/CLAUDE.md. These operational scripts have no human-readable documentation. DOC-4 or DOC-5 should document what each script does and when to use it.Recommendations
docker compose upon the production overlay, Health verification, First-run database seed.docs/infrastructure/production-compose.mdfor the full Compose file details rather than duplicating it. DOC-5 is the entry point; the infrastructure docs are the reference./health. The training endpoint requiresX-Training-Token."scripts/CLAUDE.md: The reset-db and clean-e2e-data scripts are operationally significant. Their migration target is CONTRIBUTING.md ("Development scripts") or DOC-5 ("Operational scripts"), not deletion. Flag which is which before migrating.📋 Elicit — Requirements Engineer
Observations
Scope clarity issues:
docs/infrastructure/docs have undefined overlap.production-compose.mdands3-migration.mdalready exist. The acceptance criterion for DOC-5 ("covers all production runtime concerns") is ambiguous: does it duplicate what's in these files, supersede them, or link to them? This is untestable as written.controller/,service/,repository/,model/,dto/,exception/,security/,config/,audit/,dashboard/,relationship/on the backend — that's 11. On the frontend,components/document/,components/chronik/,components/user/, routes subdirectories. The actual list differs from the estimate and affects scope.Missing acceptance criteria:
Recommendations
# Layering Rules → See CONTRIBUTING.md#backend-walkthrough), and the CLAUDE.md retains only LLM workflow instructions." This makes the AC auditable.🗳️ Decision Queue — Action Required
4 decisions need your input before implementation starts.
Scope
DOC-5 vs. existing
docs/infrastructure/docs —production-compose.md,s3-migration.md,ci-gitea.md, andself-hosted-catalogue.mdalready exist and cover substantial production runtime concerns. Does DOC-5 (a) supersede and consolidate them into one file, (b) become a thin entry-point that links into those files, or (c) duplicate them? Option (a) costs more to write but creates one canonical source; option (b) is cheap but depends on those files being complete and maintained; option (c) creates long-term drift. (Raised by: Tobias, Elicit)DOC-6 package enumeration — what exactly are the "~14 files"? The backend has at least 11 Java packages (
controller,service,repository,model,dto,exception,security,config,audit,dashboard,relationship), and the frontend has several component subdirectories. The estimate of 14 is likely off. Enumerate the exact target list before child issues are created, or implementations will have mismatched scope. (Raised by: Elicit)Process
DOC-7 definition of "migrated" — When a CLAUDE.md rule moves to a human doc, does the CLAUDE.md section (a) get deleted entirely, (b) get replaced with a pointer comment (
# → CONTRIBUTING.md#backend-layering), or (c) remain as-is with only a note marking it as migrated? Option (b) is recommended because it preserves CLAUDE.md's utility for LLM agents while making the human doc the canonical source. But this needs an explicit decision so all DOC-7 work is consistent. (Raised by: Felix, Elicit)CONTRIBUTING.md walkthrough #3 — backend "add a page" or frontend SvelteKit route? The issue says "add a domain / endpoint / page" but doesn't specify if "page" means a Spring MVC controller endpoint or a SvelteKit route. Anja (backend dev persona) needs a backend walkthrough; Tobias (PM-with-CS) needs the frontend walkthrough. Both audiences are served by different content. Options: (a) two walkthroughs for "page" (one each), (b) one walkthrough that covers a full vertical slice end-to-end (migration → service → controller → SvelteKit load → component). Option (b) is higher effort but closes the mental model gap in one document. (Raised by: Felix, Markus)
✅ Decision Queue — Resolved
The four decisions raised earlier in this thread are resolved as follows. The existing child issues (#395–#401, created yesterday with persona reviews) carry these epic-level resolutions; per-child Decision Queues are addressed separately on each issue.
D1 — DOC-5 vs existing
docs/infrastructure/docs → link, don't duplicateDOC-5 (
docs/DEPLOYMENT.md) is a single-page Day-1 production checklist (per Tobias) that links into the four existing infrastructure docs. New content unique to DOC-5: the "Secrets checklist" (per Nora) listing every must-set env var with fail-fast vs dev-default classification.D2 — DOC-6 enumeration → 18 README.md files (not "~14")
Driven by the Canonical Domain Set (#387 first comment) and current backend/frontend trees on
main:document/,person/,tag/,user/,geschichte/,notification/,ocr/,audit/,dashboard/document/,person/,tag/,user/,geschichte/,notification/,ocr/,shared/ocr-service/README.mdSkipped (cross-cutting infrastructure, content lives in CONTRIBUTING.md): backend
config/,exception/,security/,filestorage/,importing/.Per Markus: every README uses a fixed 3-section template — What this domain owns / What it exposes / What it depends on.
D3 — DOC-7 definition of "migrated" → pointer-comment policy
Concrete rule, applied uniformly to all 10 CLAUDE.md files:
→ See CONTRIBUTING.md#backend-walkthrough.grep -rE "DO NOT|MUST NOT|always|never" CLAUDE.md …returns no rule-shaped sentences outside pointer blocks.D4 — CONTRIBUTING.md walkthrough #3 → frontend SvelteKit route
Three audience-targeted walkthroughs (per Felix), each H2 so the Gitea TOC links them:
Tag).Tagrename).+page.server.ts→ typed client →!result.response.okguard →+page.sveltewith$props()).Plus a Testing section (per Sara) covering all four test layers — closes the test-strategy gap that wasn't covered by any DOC-* in the original epic.
🔗 Child issues
Suggested implementation order: DOC-3 → DOC-1 → DOC-2 → DOC-4 → DOC-5 → DOC-6 → DOC-7. (DOC-7 is hard-blocked by DOC-2, DOC-4, DOC-5, DOC-6 as migration targets.)
Per-child decisions are being resolved in follow-up comments on each of #395–#401 in this session.