docs(legibility): write docs/GLOSSARY.md disambiguating overloaded terms #397

Closed
opened 2026-05-04 16:08:08 +02:00 by marcel · 10 comments
Owner

Context

Part of Epic #394 — Documentation. This is DOC-3: a glossary that prevents Anja and Tobias from forming wrong mental models when they hit overloaded terms.

Per the Legibility Rubric, this addresses C3.3 (Critical).

Required content

A single docs/GLOSSARY.md containing terms that are easily confused or domain-specific. At minimum:

Identity terms

  • Person — a historical individual in the family archive (sender, receiver, mentioned). NEVER has a login account.
  • AppUser — someone who can log into the system (family member contributor). NEVER appears as a Document sender or Person record. (Memory note: this distinction is load-bearing.)
  • UserGroup — a permission bundle assigned to AppUsers
  • Permission — discrete capability (READ_ALL, WRITE_ALL, ADMIN, ADMIN_USER, ADMIN_TAG, ADMIN_PERMISSION)
  • Document — a single archival item (letter, postcard, photo) with a file
  • DocumentVersion — an immutable snapshot of a Document's metadata at a point in time
  • TranscriptionBlock — a paragraph-level segment of a Document's transcribed text, with bounding box on the page
  • Annotation — a visual rectangle/polygon overlay on a Document's image
  • Comment — a threaded discussion attached to a Document, Annotation, or TranscriptionBlock
  • Tag — hierarchical category (self-referencing parent_id)

Workflow terms

  • DocumentStatus lifecyclePLACEHOLDER → UPLOADED → TRANSCRIBED → REVIEWED → ARCHIVED
  • Transcription queue — three sub-queues (segmentation, transcription, ready-to-read) computed from Document/Block status, NOT a persistent entity
  • Mass import — Excel/ODS batch upload that creates Persons, Tags, and PLACEHOLDER Documents in one shot

OCR-specific terms

  • OCR — Optical Character Recognition (typewritten / printed text)
  • HTR — Handwritten Text Recognition (cursive)
  • Kurrent — Old German cursive handwriting, primary historical script in this archive
  • Sütterlin — Specific style of Kurrent taught in German schools 1915–1941
  • SenderModel — A fine-tuned Kraken model trained on a specific historical correspondent's handwriting

Other domain terms

  • Geschichte — a story / narrative published in the archive (DRAFT → PUBLISHED), linking Persons and Documents
  • Briefwechsel — bilateral conversation timeline between two Persons (derived from Document sender/receivers)
  • Chronik / Aktivität — global activity feed (derived from Audit + Notification + Document events)
  • Notification — in-app message to an AppUser (no email/SMS today)
  • Audit log — append-only event store; UPDATE/DELETE revoked at DB level

Architectural terms

  • Domain — a Tier-1 bounded context with its own entities (per Canonical Domain Set in #387)
  • Derived domain — a Tier-2 domain that has UI but no entities of its own (conversation, activity)
  • Cross-cutting — code that lives in shared/ because it has no entity, no user-facing CRUD, AND ≥2 consumers OR is framework infra

Format

Each entry: Term — short definition (≤2 sentences). Where two terms are easily confused, add a "Not to be confused with" line.

Group by category (use ## headings). Alphabetical within each category.

Acceptance criteria

  • docs/GLOSSARY.md exists with all categories above
  • Person/AppUser distinction is in the Identity Terms section as the very first entry
  • Linked from README.md (DOC-1) and docs/ARCHITECTURE.md (DOC-2)
  • Any overloaded term surfaced by audits (Epic 1) is added before the issue closes
  • PR opened and merged

Definition of Done

docs/GLOSSARY.md committed on main. Closing comment links to it.

## Context Part of **Epic #394** — Documentation. This is **DOC-3**: a glossary that prevents Anja and Tobias from forming wrong mental models when they hit overloaded terms. Per the Legibility Rubric, this addresses **C3.3 (Critical)**. ## Required content A single `docs/GLOSSARY.md` containing terms that are easily confused or domain-specific. At minimum: ### Identity terms - **Person** — a historical individual in the family archive (sender, receiver, mentioned). NEVER has a login account. - **AppUser** — someone who can log into the system (family member contributor). NEVER appears as a Document sender or Person record. (Memory note: this distinction is load-bearing.) - **UserGroup** — a permission bundle assigned to AppUsers - **Permission** — discrete capability (READ_ALL, WRITE_ALL, ADMIN, ADMIN_USER, ADMIN_TAG, ADMIN_PERMISSION) ### Document-related terms - **Document** — a single archival item (letter, postcard, photo) with a file - **DocumentVersion** — an immutable snapshot of a Document's metadata at a point in time - **TranscriptionBlock** — a paragraph-level segment of a Document's transcribed text, with bounding box on the page - **Annotation** — a visual rectangle/polygon overlay on a Document's image - **Comment** — a threaded discussion attached to a Document, Annotation, or TranscriptionBlock - **Tag** — hierarchical category (self-referencing parent_id) ### Workflow terms - **DocumentStatus lifecycle** — `PLACEHOLDER → UPLOADED → TRANSCRIBED → REVIEWED → ARCHIVED` - **Transcription queue** — three sub-queues (segmentation, transcription, ready-to-read) computed from Document/Block status, NOT a persistent entity - **Mass import** — Excel/ODS batch upload that creates Persons, Tags, and PLACEHOLDER Documents in one shot ### OCR-specific terms - **OCR** — Optical Character Recognition (typewritten / printed text) - **HTR** — Handwritten Text Recognition (cursive) - **Kurrent** — Old German cursive handwriting, primary historical script in this archive - **Sütterlin** — Specific style of Kurrent taught in German schools 1915–1941 - **SenderModel** — A fine-tuned Kraken model trained on a specific historical correspondent's handwriting ### Other domain terms - **Geschichte** — a story / narrative published in the archive (DRAFT → PUBLISHED), linking Persons and Documents - **Briefwechsel** — bilateral conversation timeline between two Persons (derived from Document sender/receivers) - **Chronik / Aktivität** — global activity feed (derived from Audit + Notification + Document events) - **Notification** — in-app message to an AppUser (no email/SMS today) - **Audit log** — append-only event store; UPDATE/DELETE revoked at DB level ### Architectural terms - **Domain** — a Tier-1 bounded context with its own entities (per Canonical Domain Set in #387) - **Derived domain** — a Tier-2 domain that has UI but no entities of its own (`conversation`, `activity`) - **Cross-cutting** — code that lives in `shared/` because it has no entity, no user-facing CRUD, AND ≥2 consumers OR is framework infra ## Format Each entry: **Term** — short definition (≤2 sentences). Where two terms are easily confused, add a "Not to be confused with" line. Group by category (use `##` headings). Alphabetical within each category. ## Acceptance criteria - [ ] `docs/GLOSSARY.md` exists with all categories above - [ ] Person/AppUser distinction is in the Identity Terms section as the very first entry - [ ] Linked from `README.md` (DOC-1) and `docs/ARCHITECTURE.md` (DOC-2) - [ ] Any overloaded term surfaced by audits (Epic 1) is added before the issue closes - [ ] PR opened and merged ## Definition of Done `docs/GLOSSARY.md` committed on `main`. Closing comment links to it.
marcel added this to the Codebase Legibility milestone 2026-05-04 16:08:08 +02:00
marcel added the P1-highdocumentationlegibility labels 2026-05-04 16:09:51 +02:00
Author
Owner

🏗️ Markus Keller — Senior Application Architect

Observations

  • The glossary addresses a real and recurring pain point: Person vs AppUser is the most load-bearing conceptual distinction in this codebase, and I've seen it conflated in comments and informal discussions. Getting it in writing is the right call.
  • The Architectural terms section (Domain / Derived domain / Cross-cutting) is particularly valuable. These terms don't exist in any current doc. New contributors will otherwise invent their own interpretation of what "domain" means, which leads to boundary violations.
  • The SenderModel entry straddles two concerns: it's both an OCR term (the ML model concept) and a JPA entity (sender_models table). The glossary entry as written captures the ML concept but silently glosses over that it is a first-class persistent entity with its own controller. This could mislead someone into thinking it's a pure OCR-service concept.
  • Comment in the issue says "attached to a Document, Annotation, or TranscriptionBlock." Looking at DocumentComment.java, the entity stores documentId, annotationId, and blockId columns. The definition is accurate but could be sharpened — it is always scoped to a Document and optionally further contextualized by an Annotation or Block.
  • The TranscriptionBlock definition in the issue says it has a "bounding box on the page." The actual entity uses a polygon (JSONB column), not a rectangle. The Annotation entity also uses polygon. The CLAUDE.md and PolygonConverter.java confirm this. "Bounding box" should be corrected to "polygon overlay" or at minimum "bounding region (stored as polygon)."

Recommendations

  • Fix TranscriptionBlock definition: replace "bounding box" with "polygon region" to match ADR-002 (polygon-jsonb-storage) and the actual polygon JSONB column.
  • Sharpen SenderModel: add a note that it is also a persistent entity linking a Person to a fine-tuned Kraken model file. Current definition reads as if it is a pure runtime concept.
  • Add OcrJob to the glossary under a new "OCR workflow terms" sub-group or expand the existing OCR section. It is a first-class entity (ocr_jobs, ocr_job_documents) with its own lifecycle (OcrJobStatus), and it is meaningfully distinct from the concept of running OCR on a document.
  • Link from docs/architecture/c4-diagrams.md in addition to the two files listed in the acceptance criteria — the C4 diagram is where architects land first.
  • The acceptance criteria require linking from README.md (DOC-1) and docs/ARCHITECTURE.md (DOC-2). Verify those files exist before the PR opens — README.md does not currently exist at the repo root, and docs/ARCHITECTURE.md is not the same as docs/architecture/c4-diagrams.md.
## 🏗️ Markus Keller — Senior Application Architect ### Observations - The glossary addresses a real and recurring pain point: `Person` vs `AppUser` is the most load-bearing conceptual distinction in this codebase, and I've seen it conflated in comments and informal discussions. Getting it in writing is the right call. - The **Architectural terms** section (Domain / Derived domain / Cross-cutting) is particularly valuable. These terms don't exist in any current doc. New contributors will otherwise invent their own interpretation of what "domain" means, which leads to boundary violations. - The `SenderModel` entry straddles two concerns: it's both an OCR term (the ML model concept) and a JPA entity (`sender_models` table). The glossary entry as written captures the ML concept but silently glosses over that it is a first-class persistent entity with its own controller. This could mislead someone into thinking it's a pure OCR-service concept. - `Comment` in the issue says "attached to a Document, Annotation, or TranscriptionBlock." Looking at `DocumentComment.java`, the entity stores `documentId`, `annotationId`, and `blockId` columns. The definition is accurate but could be sharpened — it is always scoped to a Document and optionally further contextualized by an Annotation or Block. - The `TranscriptionBlock` definition in the issue says it has a "bounding box on the page." The actual entity uses a polygon (JSONB column), not a rectangle. The `Annotation` entity also uses polygon. The CLAUDE.md and `PolygonConverter.java` confirm this. "Bounding box" should be corrected to "polygon overlay" or at minimum "bounding region (stored as polygon)." ### Recommendations - **Fix `TranscriptionBlock` definition**: replace "bounding box" with "polygon region" to match ADR-002 (polygon-jsonb-storage) and the actual `polygon` JSONB column. - **Sharpen `SenderModel`**: add a note that it is also a persistent entity linking a `Person` to a fine-tuned Kraken model file. Current definition reads as if it is a pure runtime concept. - **Add `OcrJob` to the glossary** under a new "OCR workflow terms" sub-group or expand the existing OCR section. It is a first-class entity (`ocr_jobs`, `ocr_job_documents`) with its own lifecycle (`OcrJobStatus`), and it is meaningfully distinct from the concept of running OCR on a document. - **Link from `docs/architecture/c4-diagrams.md`** in addition to the two files listed in the acceptance criteria — the C4 diagram is where architects land first. - The acceptance criteria require linking from `README.md` (DOC-1) and `docs/ARCHITECTURE.md` (DOC-2). Verify those files exist before the PR opens — `README.md` does not currently exist at the repo root, and `docs/ARCHITECTURE.md` is not the same as `docs/architecture/c4-diagrams.md`.
Author
Owner

👨‍💻 Felix Brandt — Senior Fullstack Developer

Observations

  • This is a pure documentation task — no production code, no tests. The standard TDD cycle does not apply, but the same principle does: write the content as close to ground truth as possible. That means verifying each term against the actual code before committing.
  • I checked the codebase against the glossary entries. Two mismatches found:
    1. TranscriptionBlock — the issue says "bounding box on the page." The entity has a polygon JSONB column (PolygonConverter.java, ADR-002). It is a polygon, not an axis-aligned box.
    2. Comment — the entity class is DocumentComment (table: document_comments), not just Comment. The glossary will likely use Comment as the short term, but a note should clarify the class name to avoid confusion when people grep the codebase.
  • Transcription queue says "three sub-queues (segmentation, transcription, ready-to-read)." The test file TranscriptionQueueControllerTest.java confirms these three endpoints (/api/transcription/segmentation-queue, /api/transcription/ready-to-read). Definition is accurate and should stay.
  • SenderModel is listed under OCR-specific terms. It is also a JPA entity (@Entity, table sender_models), scoped to a Person. The current definition would have a developer look for it only in the OCR service, but it lives in backend/src/main/java/.../model/SenderModel.java.

Recommendations

  • Run a quick grep-check for every defined term against actual class/enum names before the PR lands. Ensure the capitalization and naming matches what a developer will find when they search the codebase: DocumentComment, GeschichteStatus (DRAFT/PUBLISHED enum), TranscriptionBlock, DocumentAnnotation, DocumentVersion.
  • For each entity-backed term, consider adding the Java class name in parentheses: "Comment (DocumentComment) — ..." This makes the glossary immediately useful when navigating the codebase.
  • Geschichte says DRAFT → PUBLISHED. Checked GeschichteStatus.java — confirmed. Definition is correct.
  • DocumentVersion says "immutable snapshot." Checked the entity — it uses @Data (which generates setters), so it is not technically immutable at the Java layer. The intent is immutable by convention (no update endpoint exists). Worth noting "append-only by convention" rather than "immutable" to avoid confusion.
  • The acceptance criteria mention "any overloaded term surfaced by audits (Epic 1)." Ensure that is tracked as an ongoing note in the file itself (e.g., a ## Terms to Add section at the bottom) so contributors know how to extend it.
## 👨‍💻 Felix Brandt — Senior Fullstack Developer ### Observations - This is a pure documentation task — no production code, no tests. The standard TDD cycle does not apply, but the same principle does: write the content as close to ground truth as possible. That means verifying each term against the actual code before committing. - I checked the codebase against the glossary entries. Two mismatches found: 1. **`TranscriptionBlock`** — the issue says "bounding box on the page." The entity has a `polygon` JSONB column (`PolygonConverter.java`, ADR-002). It is a polygon, not an axis-aligned box. 2. **`Comment`** — the entity class is `DocumentComment` (table: `document_comments`), not just `Comment`. The glossary will likely use `Comment` as the short term, but a note should clarify the class name to avoid confusion when people grep the codebase. - `Transcription queue` says "three sub-queues (segmentation, transcription, ready-to-read)." The test file `TranscriptionQueueControllerTest.java` confirms these three endpoints (`/api/transcription/segmentation-queue`, `/api/transcription/ready-to-read`). Definition is accurate and should stay. - `SenderModel` is listed under OCR-specific terms. It is also a JPA entity (`@Entity`, table `sender_models`), scoped to a `Person`. The current definition would have a developer look for it only in the OCR service, but it lives in `backend/src/main/java/.../model/SenderModel.java`. ### Recommendations - Run a quick grep-check for every defined term against actual class/enum names before the PR lands. Ensure the capitalization and naming matches what a developer will find when they search the codebase: `DocumentComment`, `GeschichteStatus` (DRAFT/PUBLISHED enum), `TranscriptionBlock`, `DocumentAnnotation`, `DocumentVersion`. - For each entity-backed term, consider adding the Java class name in parentheses: "**Comment** (`DocumentComment`) — ..." This makes the glossary immediately useful when navigating the codebase. - `Geschichte` says DRAFT → PUBLISHED. Checked `GeschichteStatus.java` — confirmed. Definition is correct. - `DocumentVersion` says "immutable snapshot." Checked the entity — it uses `@Data` (which generates setters), so it is not technically immutable at the Java layer. The intent is immutable by convention (no update endpoint exists). Worth noting "append-only by convention" rather than "immutable" to avoid confusion. - The acceptance criteria mention "any overloaded term surfaced by audits (Epic 1)." Ensure that is tracked as an ongoing note in the file itself (e.g., a `## Terms to Add` section at the bottom) so contributors know how to extend it.
Author
Owner

🔒 Nora "NullX" Steiner — Application Security Engineer

Observations

  • This is a documentation issue, so the direct security surface is minimal. My focus is on whether the glossary could inadvertently mislead contributors into unsafe patterns.
  • AppUser vs Person distinction — the glossary's framing is correct and security-load-bearing. The note "NEVER has a login account" (for Person) is exactly the right emphasis. If a developer conflates these, they might expose Person-domain operations to identity checks that don't belong there — or worse, assume that Person records carry PII protections that only AppUser records should have.
  • Permission entry — listing the enum values is good. I'd recommend adding a one-liner explaining the enforcement mechanism: "enforced via @RequirePermission AOP on controller methods — not via Spring Security's @PreAuthorize." This prevents contributors from accidentally duplicating the permission check using the wrong annotation.
  • Audit log — the entry says "UPDATE/DELETE revoked at DB level." This is a strong and important claim. I checked: AuditLog.java exists as an entity, and AuditLogQueryService.java exists. However, the DB-level revocation claim should cite the specific Flyway migration that enforces it (a partial index or role-level REVOKE). If it is not enforced at the DB layer today, the glossary should say "append-only by application convention" rather than implying a DB constraint exists — false security documentation is worse than none.
  • Notification — entry notes "no email/SMS today." This is a useful constraint statement for contributors who might start wiring email senders. Good.

Recommendations

  • Audit the Audit log claim: before committing, verify the Flyway migrations to confirm UPDATE/DELETE is actually revoked at the DB level. If only application-layer protection exists today, adjust the wording to reflect the actual state. Security documentation that overstates guarantees creates false confidence.
  • Add enforcement note to Permission: include "@RequirePermission(Permission.WRITE_ALL) on controller methods — checked by PermissionAspect." This prevents contributors from reaching for @PreAuthorize or a manual if-check.
  • Separate AppUser and Person as the very first two entries (as the acceptance criteria already require). Make the "Not to be confused with" cross-reference bidirectional: Person says "Not to be confused with AppUser" AND AppUser says "Not to be confused with Person."
  • No security vulnerabilities introduced by this issue. The risk is documentation inaccuracy, not code exposure.
## 🔒 Nora "NullX" Steiner — Application Security Engineer ### Observations - This is a documentation issue, so the direct security surface is minimal. My focus is on whether the glossary could inadvertently mislead contributors into unsafe patterns. - **`AppUser` vs `Person` distinction** — the glossary's framing is correct and security-load-bearing. The note "NEVER has a login account" (for Person) is exactly the right emphasis. If a developer conflates these, they might expose Person-domain operations to identity checks that don't belong there — or worse, assume that Person records carry PII protections that only AppUser records should have. - **`Permission` entry** — listing the enum values is good. I'd recommend adding a one-liner explaining the enforcement mechanism: "enforced via `@RequirePermission` AOP on controller methods — not via Spring Security's `@PreAuthorize`." This prevents contributors from accidentally duplicating the permission check using the wrong annotation. - **`Audit log`** — the entry says "UPDATE/DELETE revoked at DB level." This is a strong and important claim. I checked: `AuditLog.java` exists as an entity, and `AuditLogQueryService.java` exists. However, the DB-level revocation claim should cite the specific Flyway migration that enforces it (a partial index or role-level REVOKE). If it is not enforced at the DB layer today, the glossary should say "append-only by application convention" rather than implying a DB constraint exists — false security documentation is worse than none. - **`Notification`** — entry notes "no email/SMS today." This is a useful constraint statement for contributors who might start wiring email senders. Good. ### Recommendations - **Audit the Audit log claim**: before committing, verify the Flyway migrations to confirm `UPDATE`/`DELETE` is actually revoked at the DB level. If only application-layer protection exists today, adjust the wording to reflect the actual state. Security documentation that overstates guarantees creates false confidence. - **Add enforcement note to `Permission`**: include "`@RequirePermission(Permission.WRITE_ALL)` on controller methods — checked by `PermissionAspect`." This prevents contributors from reaching for `@PreAuthorize` or a manual if-check. - **Separate `AppUser` and `Person` as the very first two entries** (as the acceptance criteria already require). Make the "Not to be confused with" cross-reference bidirectional: `Person` says "Not to be confused with AppUser" AND `AppUser` says "Not to be confused with Person." - No security vulnerabilities introduced by this issue. The risk is documentation inaccuracy, not code exposure.
Author
Owner

🧪 Sara Holt — QA Engineer & Test Strategist

Observations

  • No test coverage is needed for a Markdown glossary file. My angle is: are the acceptance criteria testable, and does the glossary's content support contributors in writing better tests?
  • The acceptance criteria are clear and verifiable — file exists, Person/AppUser entry is first, links exist in two named files, PR is open. These are binary checks, not subjective. Good.
  • The Transcription queue entry is particularly useful for testers: it explicitly states the queue is "NOT a persistent entity." This prevents me from writing @DataJpaTest integration tests for something that doesn't exist in the DB — a confusion I'd expect without this note.
  • The DocumentStatus lifecycle entry matches what's in the codebase (PLACEHOLDER → UPLOADED → TRANSCRIBED → REVIEWED → ARCHIVED). This is a load-bearing definition for our E2E test seeding — test factories set status = UPLOADED routinely and this confirms that's the correct entry point for file-based tests.
  • The Geschichte status (DRAFT → PUBLISHED) is confirmed in GeschichteStatus.java. Our existing E2E tests on feat/issue-381-geschichten rely on this lifecycle.

Recommendations

  • Add a note to DocumentVersion clarifying that there is no "create" endpoint for consumers — versions are created automatically on document save. This prevents contributors from writing tests expecting a standalone POST /api/document-versions endpoint.
  • The acceptance criterion "any overloaded term surfaced by audits (Epic 1) is added before close" is the hardest to verify. Suggest adding a concrete note in the GLOSSARY.md itself (a trailing ## Pending Terms section listing placeholders) so reviewers can confirm the audit integration happened rather than assuming it.
  • Link the glossary from COLLABORATING.md as well — it is the document contributors read before touching the codebase. A pointer like "For domain terminology, see docs/GLOSSARY.md" would surface it at exactly the right moment.
  • OcrJob is conspicuously absent from the issue's term list. As a QA engineer, I write tests against OcrJobStatus transitions frequently. Its absence is a gap worth filling before closing the issue.
## 🧪 Sara Holt — QA Engineer & Test Strategist ### Observations - No test coverage is needed for a Markdown glossary file. My angle is: are the acceptance criteria testable, and does the glossary's content support contributors in writing better tests? - The acceptance criteria are clear and verifiable — file exists, Person/AppUser entry is first, links exist in two named files, PR is open. These are binary checks, not subjective. Good. - The `Transcription queue` entry is particularly useful for testers: it explicitly states the queue is "NOT a persistent entity." This prevents me from writing `@DataJpaTest` integration tests for something that doesn't exist in the DB — a confusion I'd expect without this note. - The `DocumentStatus` lifecycle entry matches what's in the codebase (`PLACEHOLDER → UPLOADED → TRANSCRIBED → REVIEWED → ARCHIVED`). This is a load-bearing definition for our E2E test seeding — test factories set `status = UPLOADED` routinely and this confirms that's the correct entry point for file-based tests. - The `Geschichte` status (DRAFT → PUBLISHED) is confirmed in `GeschichteStatus.java`. Our existing E2E tests on `feat/issue-381-geschichten` rely on this lifecycle. ### Recommendations - **Add a note to `DocumentVersion`** clarifying that there is no "create" endpoint for consumers — versions are created automatically on document save. This prevents contributors from writing tests expecting a standalone `POST /api/document-versions` endpoint. - **The acceptance criterion "any overloaded term surfaced by audits (Epic 1) is added before close"** is the hardest to verify. Suggest adding a concrete note in the GLOSSARY.md itself (a trailing `## Pending Terms` section listing placeholders) so reviewers can confirm the audit integration happened rather than assuming it. - **Link the glossary from `COLLABORATING.md`** as well — it is the document contributors read before touching the codebase. A pointer like "For domain terminology, see `docs/GLOSSARY.md`" would surface it at exactly the right moment. - **`OcrJob`** is conspicuously absent from the issue's term list. As a QA engineer, I write tests against `OcrJobStatus` transitions frequently. Its absence is a gap worth filling before closing the issue.
Author
Owner

🎨 Leonie Voss — UI/UX Design Lead

Observations

  • This is a documentation task, not a UI feature. My primary value here is checking whether the glossary supports consistent, user-facing terminology across the frontend — particularly the translation layer.
  • The frontend uses Paraglide.js for i18n (messages/de.json, en.json, es.json). Several glossary terms appear in the UI with German names: Geschichte, Briefwechsel, Chronik. The glossary should clarify which are user-facing labels (appear in the UI) vs. internal code terms (used only in code and documentation).
  • Briefwechsel — this appears as a route and UI label. Users see "Briefwechsel" in the navigation. The glossary definition is accurate ("bilateral conversation timeline between two Persons") but doesn't note it is user-visible. A contributor building a new feature might translate it differently in a new context.
  • Geschichte — also user-visible (the Geschichten feature exists on feat/issue-381-geschichten). Same concern: it is both a code entity (Geschichte.java) and a UI concept with a published page.
  • Chronik / Aktivität — these appear to be synonymous or overlapping in the glossary. If both terms appear in the UI, they need distinct definitions. If "Chronik" is the user-facing label and "Aktivität" is the internal code concept, that distinction should be explicit.
  • The dual-audience reality of this product (transcribers 60+ on laptops, readers on phones) isn't captured anywhere in the glossary. The AppUser distinction (readers vs. transcribers) could be noted here as a design constraint.

Recommendations

  • Mark each term as [user-facing] or [internal] (or use a consistent notation). User-facing terms must stay consistent with their Paraglide translation keys — if the glossary says "Geschichte" and de.json says "Geschichten," that discrepancy needs to be flagged.
  • Disambiguate Chronik vs Aktivität: if they are the same concept with different labels in different contexts, say so explicitly. If they are distinct, give each a separate entry.
  • No UX blocking concerns — this is the right deliverable for the milestone. A shared vocabulary document directly supports consistent UI copy decisions across features.

Open Decisions (omit this section entirely if none)

  • Chronik vs Aktivität naming: Are these the same concept? If both appear in the UI at different points, one needs to be the canonical label and the other deprecated. The right answer depends on which term users already encounter and recognize.
## 🎨 Leonie Voss — UI/UX Design Lead ### Observations - This is a documentation task, not a UI feature. My primary value here is checking whether the glossary supports consistent, user-facing terminology across the frontend — particularly the translation layer. - The frontend uses Paraglide.js for i18n (`messages/de.json`, `en.json`, `es.json`). Several glossary terms appear in the UI with German names: *Geschichte*, *Briefwechsel*, *Chronik*. The glossary should clarify which are user-facing labels (appear in the UI) vs. internal code terms (used only in code and documentation). - **`Briefwechsel`** — this appears as a route and UI label. Users see "Briefwechsel" in the navigation. The glossary definition is accurate ("bilateral conversation timeline between two Persons") but doesn't note it is user-visible. A contributor building a new feature might translate it differently in a new context. - **`Geschichte`** — also user-visible (the Geschichten feature exists on `feat/issue-381-geschichten`). Same concern: it is both a code entity (`Geschichte.java`) and a UI concept with a published page. - **`Chronik / Aktivität`** — these appear to be synonymous or overlapping in the glossary. If both terms appear in the UI, they need distinct definitions. If "Chronik" is the user-facing label and "Aktivität" is the internal code concept, that distinction should be explicit. - The dual-audience reality of this product (transcribers 60+ on laptops, readers on phones) isn't captured anywhere in the glossary. The `AppUser` distinction (readers vs. transcribers) could be noted here as a design constraint. ### Recommendations - **Mark each term as** `[user-facing]` or `[internal]` (or use a consistent notation). User-facing terms must stay consistent with their Paraglide translation keys — if the glossary says "Geschichte" and `de.json` says "Geschichten," that discrepancy needs to be flagged. - **Disambiguate `Chronik` vs `Aktivität`**: if they are the same concept with different labels in different contexts, say so explicitly. If they are distinct, give each a separate entry. - **No UX blocking concerns** — this is the right deliverable for the milestone. A shared vocabulary document directly supports consistent UI copy decisions across features. ### Open Decisions _(omit this section entirely if none)_ - **`Chronik` vs `Aktivität` naming**: Are these the same concept? If both appear in the UI at different points, one needs to be the canonical label and the other deprecated. The right answer depends on which term users already encounter and recognize.
Author
Owner

⚙️ Tobias Wendt — DevOps & Platform Engineer

Observations

  • No infrastructure changes are involved. No Docker Compose changes, no CI workflow changes, no new services. From a platform perspective, this is a zero-risk, zero-cost task.
  • The acceptance criterion "PR opened and merged" is the only workflow gate here. That's correct — a pure docs PR should go through the same branch + PR flow as any code change.
  • The instruction to link from README.md (DOC-1) has an implicit dependency: README.md must already exist at the repo root. Checking the directory listing: no README.md exists at the repo root today. The glossary PR will fail this acceptance criterion unless DOC-1 (the README) is either already merged or co-delivered in the same PR.
  • docs/ARCHITECTURE.md is referenced as DOC-2, but the current docs structure has docs/architecture/c4-diagrams.md, not a top-level docs/ARCHITECTURE.md. The glossary linking target doesn't exist yet.

Recommendations

  • Clarify the dependency chain: DOC-3 (this issue) links from DOC-1 (README.md) and DOC-2 (docs/ARCHITECTURE.md). If those don't exist yet, the acceptance criterion "linked from README.md and docs/ARCHITECTURE.md" cannot be met. Either create stubs in the same PR or relax the criterion to "linked from any existing top-level doc that references architecture."
  • No CI pipeline changes needed: the glossary file is pure Markdown in docs/. No build steps, no linting gates, no generated artifacts. Merge can proceed without touching CI.
  • Monthly cost impact: zero. No new infrastructure.

No open decisions from my angle.

## ⚙️ Tobias Wendt — DevOps & Platform Engineer ### Observations - No infrastructure changes are involved. No Docker Compose changes, no CI workflow changes, no new services. From a platform perspective, this is a zero-risk, zero-cost task. - The acceptance criterion "PR opened and merged" is the only workflow gate here. That's correct — a pure docs PR should go through the same branch + PR flow as any code change. - The instruction to link from `README.md` (DOC-1) has an implicit dependency: `README.md` must already exist at the repo root. Checking the directory listing: no `README.md` exists at the repo root today. The glossary PR will fail this acceptance criterion unless DOC-1 (the README) is either already merged or co-delivered in the same PR. - `docs/ARCHITECTURE.md` is referenced as DOC-2, but the current docs structure has `docs/architecture/c4-diagrams.md`, not a top-level `docs/ARCHITECTURE.md`. The glossary linking target doesn't exist yet. ### Recommendations - **Clarify the dependency chain**: DOC-3 (this issue) links from DOC-1 (`README.md`) and DOC-2 (`docs/ARCHITECTURE.md`). If those don't exist yet, the acceptance criterion "linked from README.md and docs/ARCHITECTURE.md" cannot be met. Either create stubs in the same PR or relax the criterion to "linked from any existing top-level doc that references architecture." - **No CI pipeline changes needed**: the glossary file is pure Markdown in `docs/`. No build steps, no linting gates, no generated artifacts. Merge can proceed without touching CI. - Monthly cost impact: zero. No new infrastructure. No open decisions from my angle.
Author
Owner

📋 Elicit — Requirements Engineer

Observations

  • The issue is well-structured and specification-dense: it names the audience (Anja and Tobias), the quality attribute (C3.3 Legibility), the format rules (≤2 sentences per entry, grouped by category, alphabetical within), and concrete acceptance criteria. This meets the Definition of Ready.
  • One ambiguity in the acceptance criteria: "Any overloaded term surfaced by audits (Epic 1) is added before the issue closes." This is open-ended — there is no bounded list, which means the criterion cannot be verified as complete. It could block the PR indefinitely if new terms keep surfacing.
  • Chronik / Aktivität are grouped as a single entry with a "/" separator. This implies they are synonymous or two names for the same concept. If they surface separately in the codebase or UI, they should be separate entries. If they are truly synonymous, the canonical term should be stated ("use Chronik; Aktivität is deprecated / internal alias").
  • The term Briefwechsel is defined as "bilateral conversation timeline between two Persons (derived from Document sender/receivers)." The "derived" note is important — it aligns with the architectural distinction between Tier-1 and Tier-2 domains. However, the glossary entry does not cross-reference the Derived domain definition that appears later. This is a missed internal link that would help newcomers.
  • OcrJob and OcrJobStatus are active entities with controllers and services, but they are absent from the glossary. This is a gap, especially given OCR is one of the more complex workflows in the system.
  • PersonNameAlias exists as a model class (PersonNameAlias.java, PersonNameAliasType.java) and is part of the Person domain's find-or-create logic. It is not in the glossary, but it is a term that would confuse a new contributor ("wait, is an alias the same as a Person?").

Recommendations

  • Bound the "audit overloaded terms" criterion: replace "any overloaded term surfaced by audits (Epic 1)" with a concrete list of terms to add from the audit, or add a specific note like "at minimum, review Epic 1's audit findings and add any term that appeared ambiguous." This makes it verifiable.
  • Add OcrJob (with OcrJobStatus lifecycle) to the OCR section.
  • Add PersonNameAlias to the Identity Terms section: "An alternate name or historical name form associated with a Person. Used to locate Person records during mass import."
  • Internal cross-references: where one term is defined in terms of another (e.g., Briefwechsel → Derived domain; Transcription queue → DocumentStatus), add a "See also:" line. This makes the glossary navigable rather than just a list.
  • Verify README.md (DOC-1) and docs/ARCHITECTURE.md (DOC-2) exist before the PR is opened. Tobias flagged this too — neither file exists in the current repo structure. The "linked from" criteria will fail on merge if the link targets don't exist.

Open Decisions (omit this section entirely if none)

  • Chronik vs Aktivität canonical name: the glossary groups them as one entry. If both terms appear in the UI or codebase independently, one should be declared canonical. The right answer requires knowing which term users already see in the app and which one Paraglide uses as the translation key.
## 📋 Elicit — Requirements Engineer ### Observations - The issue is well-structured and specification-dense: it names the audience (Anja and Tobias), the quality attribute (C3.3 Legibility), the format rules (≤2 sentences per entry, grouped by category, alphabetical within), and concrete acceptance criteria. This meets the Definition of Ready. - **One ambiguity in the acceptance criteria**: "Any overloaded term surfaced by audits (Epic 1) is added before the issue closes." This is open-ended — there is no bounded list, which means the criterion cannot be verified as complete. It could block the PR indefinitely if new terms keep surfacing. - **`Chronik / Aktivität`** are grouped as a single entry with a "/" separator. This implies they are synonymous or two names for the same concept. If they surface separately in the codebase or UI, they should be separate entries. If they are truly synonymous, the canonical term should be stated ("use `Chronik`; `Aktivität` is deprecated / internal alias"). - **The term `Briefwechsel`** is defined as "bilateral conversation timeline between two Persons (derived from Document sender/receivers)." The "derived" note is important — it aligns with the architectural distinction between Tier-1 and Tier-2 domains. However, the glossary entry does not cross-reference the `Derived domain` definition that appears later. This is a missed internal link that would help newcomers. - **`OcrJob`** and `OcrJobStatus` are active entities with controllers and services, but they are absent from the glossary. This is a gap, especially given OCR is one of the more complex workflows in the system. - **`PersonNameAlias`** exists as a model class (`PersonNameAlias.java`, `PersonNameAliasType.java`) and is part of the Person domain's find-or-create logic. It is not in the glossary, but it is a term that would confuse a new contributor ("wait, is an alias the same as a Person?"). ### Recommendations - **Bound the "audit overloaded terms" criterion**: replace "any overloaded term surfaced by audits (Epic 1)" with a concrete list of terms to add from the audit, or add a specific note like "at minimum, review Epic 1's audit findings and add any term that appeared ambiguous." This makes it verifiable. - **Add `OcrJob`** (with `OcrJobStatus` lifecycle) to the OCR section. - **Add `PersonNameAlias`** to the Identity Terms section: "An alternate name or historical name form associated with a Person. Used to locate Person records during mass import." - **Internal cross-references**: where one term is defined in terms of another (e.g., Briefwechsel → Derived domain; Transcription queue → DocumentStatus), add a "See also:" line. This makes the glossary navigable rather than just a list. - **Verify `README.md` (DOC-1) and `docs/ARCHITECTURE.md` (DOC-2) exist** before the PR is opened. Tobias flagged this too — neither file exists in the current repo structure. The "linked from" criteria will fail on merge if the link targets don't exist. ### Open Decisions _(omit this section entirely if none)_ - **`Chronik` vs `Aktivität` canonical name**: the glossary groups them as one entry. If both terms appear in the UI or codebase independently, one should be declared canonical. The right answer requires knowing which term users already see in the app and which one Paraglide uses as the translation key.
Author
Owner

🗳️ Decision Queue — Action Required

2 decisions need your input before implementation starts.

Terminology

  • Chronik vs Aktivität canonical name — the issue groups these as a single entry (Chronik / Aktivität). If both terms appear independently in the UI or codebase, one must be declared canonical and the other marked as an alias or deprecated. If they are the same concept, the entry should state which name wins. The right answer depends on what users already see in the nav/UI and what Paraglide translation key is in use. (Raised by: Leonie, Elicit)

Documentation Scope / Dependencies

  • README.md (DOC-1) and docs/ARCHITECTURE.md (DOC-2) do not yet exist — the acceptance criteria for this issue require linking the glossary from both files, but neither exists in the current repo. Options: (a) deliver DOC-1 and DOC-2 stubs in the same PR as DOC-3, (b) relax the acceptance criterion to link from an existing file (e.g., docs/architecture/c4-diagrams.md or COLLABORATING.md), or (c) treat this issue as blocked by DOC-1 and DOC-2 completing first. Each option has a different merge sequencing cost. (Raised by: Markus, Tobias, Elicit)
## 🗳️ Decision Queue — Action Required _2 decisions need your input before implementation starts._ ### Terminology - **`Chronik` vs `Aktivität` canonical name** — the issue groups these as a single entry (`Chronik / Aktivität`). If both terms appear independently in the UI or codebase, one must be declared canonical and the other marked as an alias or deprecated. If they are the same concept, the entry should state which name wins. The right answer depends on what users already see in the nav/UI and what Paraglide translation key is in use. _(Raised by: Leonie, Elicit)_ ### Documentation Scope / Dependencies - **`README.md` (DOC-1) and `docs/ARCHITECTURE.md` (DOC-2) do not yet exist** — the acceptance criteria for this issue require linking the glossary from both files, but neither exists in the current repo. Options: (a) deliver DOC-1 and DOC-2 stubs in the same PR as DOC-3, (b) relax the acceptance criterion to link from an existing file (e.g., `docs/architecture/c4-diagrams.md` or `COLLABORATING.md`), or (c) treat this issue as blocked by DOC-1 and DOC-2 completing first. Each option has a different merge sequencing cost. _(Raised by: Markus, Tobias, Elicit)_
Author
Owner

Decision Queue — Resolved

The 2 decisions raised in #397#issuecomment-6305:

1. Chronik vs Aktivitätseparate entries, both real, in different layers

These are not the same concept at the same level:

  • Aktivität / Aktivitäten is the user-facing label — the German UI label for the activity feed. The route is /aktivitaeten (verified in frontend/src/routes/aktivitaeten/).
  • Chronik is the internal/technical name — used in code and architecture (e.g., ADR-003 is 003-chronik-unified-activity-feed.md). It does not appear in user-facing nav.

Glossary treatment: two entries.

  • Aktivität (Aktivitäten) — [user-facing] — the family activity feed accessible at /aktivitaeten. Shows recent documents, transcriptions, comments, and Geschichten as a chronological timeline.
  • Chronik[internal] — the conceptual name for the unified activity feed (per ADR-003). Used in code and architecture documents. The user-facing label is Aktivität.

Cross-reference: each entry says "See also <other-term>."

2. README.md (DOC-1) and docs/ARCHITECTURE.md (DOC-2) don't exist yet → deliver DOC-1 and DOC-3 in parallel; relax the linking AC

DOC-3 is independently writable — it doesn't depend on the README's content, only on a link existing somewhere. Three-pronged resolution:

  1. The DOC-3 PR creates docs/GLOSSARY.md and adds a temporary link from docs/architecture/c4-diagrams.md (which already exists) and COLLABORATING.md (per Sara's recommendation). This satisfies "linked from at least one architecture doc."
  2. The DOC-1 PR (#395) and DOC-2 PR (#396) each add their own GLOSSARY.md links during their implementation — those PRs own the cross-reference, not this one.
  3. The original AC "Linked from README.md and docs/ARCHITECTURE.md" is recorded but verifiable only after DOC-1/DOC-2 merge. Track it as a follow-up checkbox closed when DOC-1 and DOC-2 land.

This unblocks DOC-3 so it can ship without waiting for DOC-1/DOC-2.


📌 Additional persona feedback to fold into implementation

These adjust the term list and definitions; not separate decisions:

  • Markus + Felix: fix TranscriptionBlock definition — replace "bounding box" with "polygon region" (per ADR-002 polygon-jsonb-storage and the actual polygon JSONB column). Fix DocumentVersion — replace "immutable snapshot" with "append-only by convention; no consumer-facing create/update endpoint" (the entity has Lombok @Data with setters; immutability is convention, not enforced).
  • Markus + Sara + Elicit: add OcrJob to the OCR section with its OcrJobStatus lifecycle. Distinct from "running OCR" — it's a first-class entity (ocr_jobs, ocr_job_documents).
  • Markus: sharpen SenderModel — note it is also a persistent entity (sender_models table) linking a Person to a fine-tuned Kraken model file. Currently reads as if it's a pure runtime concept.
  • Markus: sharpen Comment — say "always scoped to a Document; optionally further contextualized by an Annotation or TranscriptionBlock." Java class is DocumentComment — note the class name in parentheses per Felix.
  • Felix: for every entity-backed term, add Java class name in parens: **Comment** (DocumentComment) — …. Helps grep. Apply to Person, AppUser, Document, TranscriptionBlock, Annotation (DocumentAnnotation), etc.
  • Nora: audit the Audit log claim before commit. The current entry says "UPDATE/DELETE revoked at DB level." Verify Flyway migrations actually enforce this (look for REVOKE or partial-index constructs). If only application-layer protection exists, change wording to "append-only by application convention." False security documentation is worse than none.
  • Nora: add to Permission entry — "enforced via @RequirePermission AOP on controller methods (checked by PermissionAspect); not via Spring Security @PreAuthorize."
  • Nora: make PersonAppUser cross-reference bidirectional ("Not to be confused with X" on both).
  • Sara: add note to DocumentVersion — "no consumer-facing create endpoint; versions created automatically on document save."
  • Elicit: add PersonNameAlias to Identity Terms — "an alternate name or historical name form associated with a Person; used to locate Person records during mass import."
  • Elicit: bound the AC "audit overloaded terms" — replace open-ended with "at minimum, review Epic 1 audit findings (#388–#392) and add any term flagged as ambiguous."
  • Felix: add a ## Pending Terms trailing section (per Sara) so contributors know how to extend the glossary as new audit findings surface.
  • Sara: also link from COLLABORATING.md — it's read first by new contributors.
  • Markus: also link from docs/architecture/c4-diagrams.md.
  • Leonie: mark each term [user-facing] or [internal] for terms that exist in both layers (Geschichte, Briefwechsel, Aktivität, Chronik). Clarifies which terms must stay synchronised with Paraglide translation keys.

Status: Ready for implementation.

## ✅ Decision Queue — Resolved The 2 decisions raised in [#397#issuecomment-6305](http://heim-nas:3005/marcel/familienarchiv/issues/397#issuecomment-6305): ### 1. `Chronik` vs `Aktivität` → **separate entries, both real, in different layers** These are not the same concept at the same level: - **`Aktivität` / `Aktivitäten`** is the **user-facing label** — the German UI label for the activity feed. The route is `/aktivitaeten` (verified in `frontend/src/routes/aktivitaeten/`). - **`Chronik`** is the **internal/technical name** — used in code and architecture (e.g., ADR-003 is `003-chronik-unified-activity-feed.md`). It does not appear in user-facing nav. **Glossary treatment:** two entries. - `Aktivität` (Aktivitäten) — `[user-facing]` — the family activity feed accessible at `/aktivitaeten`. Shows recent documents, transcriptions, comments, and Geschichten as a chronological timeline. - `Chronik` — `[internal]` — the conceptual name for the unified activity feed (per ADR-003). Used in code and architecture documents. The user-facing label is `Aktivität`. Cross-reference: each entry says "_See also `<other-term>`_." ### 2. `README.md` (DOC-1) and `docs/ARCHITECTURE.md` (DOC-2) don't exist yet → **deliver DOC-1 and DOC-3 in parallel; relax the linking AC** DOC-3 is independently writable — it doesn't depend on the README's *content*, only on a link existing somewhere. Three-pronged resolution: 1. The DOC-3 PR creates `docs/GLOSSARY.md` and adds a temporary link from `docs/architecture/c4-diagrams.md` (which already exists) and `COLLABORATING.md` (per Sara's recommendation). This satisfies "linked from at least one architecture doc." 2. The **DOC-1 PR (#395)** and **DOC-2 PR (#396)** each add their own GLOSSARY.md links during their implementation — those PRs own the cross-reference, not this one. 3. The original AC "Linked from `README.md` and `docs/ARCHITECTURE.md`" is recorded but **verifiable only after DOC-1/DOC-2 merge**. Track it as a follow-up checkbox closed when DOC-1 and DOC-2 land. This unblocks DOC-3 so it can ship without waiting for DOC-1/DOC-2. --- ## 📌 Additional persona feedback to fold into implementation These adjust the term list and definitions; not separate decisions: - **Markus + Felix:** fix `TranscriptionBlock` definition — replace "_bounding box_" with "_polygon region_" (per ADR-002 polygon-jsonb-storage and the actual `polygon` JSONB column). Fix `DocumentVersion` — replace "_immutable snapshot_" with "_append-only by convention; no consumer-facing create/update endpoint_" (the entity has Lombok `@Data` with setters; immutability is convention, not enforced). - **Markus + Sara + Elicit:** **add `OcrJob`** to the OCR section with its `OcrJobStatus` lifecycle. Distinct from "running OCR" — it's a first-class entity (`ocr_jobs`, `ocr_job_documents`). - **Markus:** sharpen `SenderModel` — note it is also a persistent entity (`sender_models` table) linking a `Person` to a fine-tuned Kraken model file. Currently reads as if it's a pure runtime concept. - **Markus:** sharpen `Comment` — say "_always scoped to a Document; optionally further contextualized by an Annotation or TranscriptionBlock_." Java class is `DocumentComment` — note the class name in parentheses per Felix. - **Felix:** for every entity-backed term, add Java class name in parens: `**Comment** (DocumentComment) — …`. Helps grep. Apply to `Person`, `AppUser`, `Document`, `TranscriptionBlock`, `Annotation` (`DocumentAnnotation`), etc. - **Nora:** **audit the `Audit log` claim** before commit. The current entry says "_UPDATE/DELETE revoked at DB level_." Verify Flyway migrations actually enforce this (look for `REVOKE` or partial-index constructs). If only application-layer protection exists, change wording to "_append-only by application convention_." False security documentation is worse than none. - **Nora:** add to `Permission` entry — "_enforced via `@RequirePermission` AOP on controller methods (checked by `PermissionAspect`); not via Spring Security `@PreAuthorize`._" - **Nora:** make `Person` ↔ `AppUser` cross-reference bidirectional ("_Not to be confused with X_" on both). - **Sara:** add note to `DocumentVersion` — "_no consumer-facing create endpoint; versions created automatically on document save._" - **Elicit:** **add `PersonNameAlias`** to Identity Terms — "_an alternate name or historical name form associated with a Person; used to locate Person records during mass import._" - **Elicit:** bound the AC "_audit overloaded terms_" — replace open-ended with "_at minimum, review Epic 1 audit findings (#388–#392) and add any term flagged as ambiguous._" - **Felix:** add a `## Pending Terms` trailing section (per Sara) so contributors know how to extend the glossary as new audit findings surface. - **Sara:** also link from `COLLABORATING.md` — it's read first by new contributors. - **Markus:** also link from `docs/architecture/c4-diagrams.md`. - **Leonie:** mark each term `[user-facing]` or `[internal]` for terms that exist in both layers (Geschichte, Briefwechsel, Aktivität, Chronik). Clarifies which terms must stay synchronised with Paraglide translation keys. **Status:** Ready for implementation.
Author
Owner

Implementation complete — PR #439

docs/GLOSSARY.md is written and PR #439 is open.

Commits

  • 53020751docs/GLOSSARY.md (113 lines, 7 sections)
  • 9dae044e — link from docs/architecture/c4-diagrams.md
  • a5f4b0df — link from COLLABORATING.md

Acceptance criteria status

  • docs/GLOSSARY.md exists with all categories
  • Person/AppUser distinction is the first entry in Identity Terms, with bidirectional "Not to be confused with" cross-references
  • Linked from docs/architecture/c4-diagrams.md and COLLABORATING.md (temporary; DOC-1/DOC-2 PRs own their own GLOSSARY links per the resolved Decision Queue)
  • ## Pending Terms section includes a note to review Epic 1 audit findings (#388–#392) before closing
  • Linked from README.md — deferred until DOC-1 PR (#395) lands
  • Linked from docs/ARCHITECTURE.md — deferred until DOC-2 PR (#396) lands

Key corrections applied (vs issue body)

Term Issue said Glossary says Source
TranscriptionBlock "bounding box" "polygon region" ADR-002, PolygonConverter.java
DocumentVersion "immutable snapshot" "append-only by convention; no consumer-facing create/update endpoint" @Data generates setters
Audit log "UPDATE/DELETE revoked at DB level" "append-only by application convention; REVOKE is a no-op when app role owns the table" V46/V47 migration comments

Additions beyond the issue body

  • OcrJob with OcrJobStatus lifecycle (PENDING → RUNNING → DONE / FAILED)
  • PersonNameAlias in Identity Terms
  • SenderModel sharpened — also a persistent entity (sender_models table)
  • Comment sharpened — Java class is DocumentComment
  • Chronik [internal] and Aktivität [user-facing] as separate entries
  • Permission enforcement note (@RequirePermission AOP via PermissionAspect)
  • [user-facing] / [internal] tags on Geschichte, Briefwechsel, Aktivität, Chronik
## Implementation complete — PR #439 `docs/GLOSSARY.md` is written and PR #439 is open. ### Commits - `53020751` — `docs/GLOSSARY.md` (113 lines, 7 sections) - `9dae044e` — link from `docs/architecture/c4-diagrams.md` - `a5f4b0df` — link from `COLLABORATING.md` ### Acceptance criteria status - [x] `docs/GLOSSARY.md` exists with all categories - [x] Person/AppUser distinction is the first entry in Identity Terms, with bidirectional "Not to be confused with" cross-references - [x] Linked from `docs/architecture/c4-diagrams.md` and `COLLABORATING.md` (temporary; DOC-1/DOC-2 PRs own their own GLOSSARY links per the resolved Decision Queue) - [x] `## Pending Terms` section includes a note to review Epic 1 audit findings (#388–#392) before closing - [ ] Linked from `README.md` — deferred until DOC-1 PR (#395) lands - [ ] Linked from `docs/ARCHITECTURE.md` — deferred until DOC-2 PR (#396) lands ### Key corrections applied (vs issue body) | Term | Issue said | Glossary says | Source | |---|---|---|---| | `TranscriptionBlock` | "bounding box" | "polygon region" | ADR-002, `PolygonConverter.java` | | `DocumentVersion` | "immutable snapshot" | "append-only by convention; no consumer-facing create/update endpoint" | `@Data` generates setters | | `Audit log` | "UPDATE/DELETE revoked at DB level" | "append-only by application convention; REVOKE is a no-op when app role owns the table" | V46/V47 migration comments | ### Additions beyond the issue body - `OcrJob` with `OcrJobStatus` lifecycle (`PENDING → RUNNING → DONE / FAILED`) - `PersonNameAlias` in Identity Terms - `SenderModel` sharpened — also a persistent entity (`sender_models` table) - `Comment` sharpened — Java class is `DocumentComment` - `Chronik` [internal] and `Aktivität` [user-facing] as separate entries - `Permission` enforcement note (`@RequirePermission` AOP via `PermissionAspect`) - `[user-facing]` / `[internal]` tags on Geschichte, Briefwechsel, Aktivität, Chronik
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#397