Remove the read-only "Originaltext" date field that confuses editors (#710) #712

Merged
marcel merged 4 commits from feat/issue-710-remove-originaltext into main 2026-06-01 20:35:40 +02:00
Owner

Closes #710.

What

Removes the read-only "Originaltext:" date field (the verbatim import cell, metaDateRaw) from everywhere it was visible in the frontend. The data stays untouched in the backend — we only stop showing and re-submitting it.

metaDateRaw had two roles; only the visible one is removed:

  • The confusing "Originaltext:" line (edit form + detail views) — gone.
  • The internal feed into the SEASON-word formatter (seasonFromRaw) — kept, so no date label silently changes.

Changes (frontend only — no backend change)

File Change
WhoWhenSection.svelte Removed the {#if rawDate} block (visible text + the hidden metaDateRaw round-trip input) and the rawDate prop.
DocumentEditLayout.svelte Dropped the rawDate=… prop passed into WhoWhenSection.
DocumentDate.svelte Removed the visible "Originaltext: …" secondary line, the showRaw prop, the showRawLine derived, and the stale CWE-79/WCAG comment. Kept the raw prop (feeds the season word).
DocumentRow.svelte Removed the two now-invalid showRaw={false} props and the comment justifying them.
DocumentMetadataDrawer.svelte Tightened the date-cell guard from {#if documentDate || metaDateRaw} to {#if documentDate} so a raw-only/undated document shows "—" instead of leaking raw text.
documentDate.ts Removed stale comments describing the raw cell as a "visible secondary line".
messages/{de,en,es}.json Deleted the now-unused date_original_label key.

Tests

  • WhoWhenSection test flipped to assert the raw block and the hidden input[name="metaDateRaw"] are absent — this guards the core "no round-trip" acceptance criterion.
  • Removed the two DocumentDate tests asserting on the deleted DOM sink (UNKNOWN secondary line + its XSS-escaping). DAY/MONTH coverage kept. No XSS surface is lost — the only surviving raw consumer is seasonFromRaw, which matches a fixed allowlist and never emits raw text.
  • Added a DocumentMetadataDrawer test: an undated, raw-only document renders "—" and never surfaces the raw text.

Verification

  • npm run lint (clean)
  • npm run check (no new errors vs. main baseline)
  • Browser-project (Playwright) component tests run in CI.
  • No backend change.

🤖 Generated with Claude Code

Closes #710. ## What Removes the read-only **"Originaltext:"** date field (the verbatim import cell, `metaDateRaw`) from everywhere it was visible in the frontend. The data stays untouched in the backend — we only stop showing and re-submitting it. `metaDateRaw` had two roles; only the **visible** one is removed: - ❌ The confusing "Originaltext:" line (edit form + detail views) — gone. - ✅ The internal feed into the SEASON-word formatter (`seasonFromRaw`) — kept, so no date label silently changes. ## Changes (frontend only — no backend change) | File | Change | |---|---| | `WhoWhenSection.svelte` | Removed the `{#if rawDate}` block (visible text **+ the hidden `metaDateRaw` round-trip input**) and the `rawDate` prop. | | `DocumentEditLayout.svelte` | Dropped the `rawDate=…` prop passed into `WhoWhenSection`. | | `DocumentDate.svelte` | Removed the visible "Originaltext: …" secondary line, the `showRaw` prop, the `showRawLine` derived, and the stale CWE-79/WCAG comment. **Kept** the `raw` prop (feeds the season word). | | `DocumentRow.svelte` | Removed the two now-invalid `showRaw={false}` props and the comment justifying them. | | `DocumentMetadataDrawer.svelte` | Tightened the date-cell guard from `{#if documentDate \|\| metaDateRaw}` to `{#if documentDate}` so a raw-only/undated document shows "—" instead of leaking raw text. | | `documentDate.ts` | Removed stale comments describing the raw cell as a "visible secondary line". | | `messages/{de,en,es}.json` | Deleted the now-unused `date_original_label` key. | ## Tests - `WhoWhenSection` test flipped to assert the raw block **and** the hidden `input[name="metaDateRaw"]` are absent — this guards the core "no round-trip" acceptance criterion. - Removed the two `DocumentDate` tests asserting on the deleted DOM sink (UNKNOWN secondary line + its XSS-escaping). DAY/MONTH coverage kept. No XSS surface is lost — the only surviving `raw` consumer is `seasonFromRaw`, which matches a fixed allowlist and never emits raw text. - Added a `DocumentMetadataDrawer` test: an undated, raw-only document renders "—" and never surfaces the raw text. ## Verification - `npm run lint` ✅ (clean) - `npm run check` ✅ (no new errors vs. `main` baseline) - Browser-project (Playwright) component tests run in CI. - No backend change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
marcel added 4 commits 2026-06-01 20:11:31 +02:00
The "Originaltext:" line in WhoWhenSection rendered the verbatim import
cell (metaDateRaw) as static text plus a hidden input that re-submitted
it on every save. Editors mistook it for an editable field. Remove the
visible line, the hidden round-trip input, and the now-unused rawDate
prop (here and at the DocumentEditLayout call site). The backend's
partial update preserves the stored value, so no data is lost.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
DocumentDate rendered an "Originaltext: <raw>" secondary line for
UNKNOWN/SEASON/APPROX dates, gated by a showRaw prop. Drop the visible
line, the showRaw prop, the showRawLine derived, and the now-unused
date_original_label message import. The raw prop stays — it still feeds
the SEASON word in formatDocumentDate, which only ever maps a fixed
German season token (never emits raw text), so no XSS surface remains.

Update both DocumentRow call sites to drop the now-gone showRaw={false}
and the comment that justified it. Remove the two DocumentDate tests
that asserted on the deleted DOM sink (the UNKNOWN secondary line and
its XSS-escaping); the DAY/MONTH coverage stays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The detail drawer's date cell rendered DocumentDate whenever a date OR a
raw cell was present (`{#if documentDate || metaDateRaw}`). For an
undated, raw-only document that meant the verbatim import text leaked
into the view. Tighten the guard to `{#if documentDate}` so such a
document shows "—". The raw prop is still passed through for the SEASON
word on dated documents. Covered by a new test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chore(i18n): drop the unused date_original_label key and stale comments
All checks were successful
CI / Unit & Component Tests (pull_request) Successful in 3m18s
CI / OCR Service Tests (pull_request) Successful in 22s
CI / Backend Unit Tests (pull_request) Successful in 3m39s
CI / fail2ban Regex (pull_request) Successful in 46s
CI / Semgrep Security Scan (pull_request) Successful in 21s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m5s
CI / Unit & Component Tests (push) Successful in 3m19s
CI / OCR Service Tests (push) Successful in 24s
CI / Backend Unit Tests (push) Successful in 3m37s
CI / fail2ban Regex (push) Successful in 44s
CI / Semgrep Security Scan (push) Successful in 21s
CI / Compose Bucket Idempotency (push) Successful in 1m6s
8a1cc2d1f0
With the visible "Originaltext" line gone from every view, the
date_original_label message has no remaining references — remove it from
de/en/es. Also drop the now-inaccurate comments in documentDate.ts that
described the raw cell as "preserved separately as the visible secondary
line"; the raw cell now only feeds the SEASON word and is never shown.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author
Owner

👨‍💻 Felix Brandt — Senior Fullstack Developer

Verdict: Approved

Clean, focused deletion. The PR does exactly what it says: it removes a confusing UI element and its round-trip input while keeping the one legitimate internal consumer (seasonFromRaw). No dead code left behind, comments updated rather than orphaned, and the TDD evidence is present (tests changed alongside the production code, asserting the absence of the removed DOM).

What I checked

  • Dead code / orphaned propsshowRaw, showRawLine, and rawDate are removed everywhere they were defined and consumed (DocumentDate.svelte, WhoWhenSection.svelte, DocumentEditLayout.svelte, DocumentRow.svelte). No caller still passes showRaw= or rawDate=. ✔
  • raw prop kept correctlyDocumentDate still accepts raw and forwards it to formatDocumentDate(...), and DocumentMetadataDrawer still passes raw={metaDateRaw}. The season word path is intact. ✔
  • Comments explain why, not what — the surviving comment on raw ("used only to derive the SEASON word, never displayed") is exactly the kind of why-comment I want. The stale CWE-79/WCAG comments that described a now-deleted sink are correctly gone. ✔
  • Guard-clause tightening{#if documentDate || metaDateRaw}{#if documentDate} is the right call: it removes the only path that surfaced raw text, and the {:else} em-dash branch handles the undated case cleanly. ✔
  • i18n hygienedate_original_label dropped from all three locales (de/en/es) symmetrically. No dangling key, no orphaned usage. ✔

Suggestions (non-blocking)

  • The drawer still declares metaDateRaw as a prop and threads it through purely as the season-word source. That's correct, but a one-word rename or a short comment at the prop site (mirroring the one you added in DocumentDate.svelte) would make it obvious to the next reader that metaDateRaw is no longer a display field. Minor.

Nothing blocks merge. This is the kind of small, honest cleanup I like.

## 👨‍💻 Felix Brandt — Senior Fullstack Developer **Verdict: ✅ Approved** Clean, focused deletion. The PR does exactly what it says: it removes a confusing UI element and its round-trip input while keeping the one legitimate internal consumer (`seasonFromRaw`). No dead code left behind, comments updated rather than orphaned, and the TDD evidence is present (tests changed alongside the production code, asserting the *absence* of the removed DOM). ### What I checked - **Dead code / orphaned props** — `showRaw`, `showRawLine`, and `rawDate` are removed everywhere they were defined and consumed (`DocumentDate.svelte`, `WhoWhenSection.svelte`, `DocumentEditLayout.svelte`, `DocumentRow.svelte`). No caller still passes `showRaw=` or `rawDate=`. ✔ - **`raw` prop kept correctly** — `DocumentDate` still accepts `raw` and forwards it to `formatDocumentDate(...)`, and `DocumentMetadataDrawer` still passes `raw={metaDateRaw}`. The season word path is intact. ✔ - **Comments explain *why*, not *what*** — the surviving comment on `raw` ("used only to derive the SEASON word, never displayed") is exactly the kind of why-comment I want. The stale CWE-79/WCAG comments that described a now-deleted sink are correctly gone. ✔ - **Guard-clause tightening** — `{#if documentDate || metaDateRaw}` → `{#if documentDate}` is the right call: it removes the only path that surfaced raw text, and the `{:else}` em-dash branch handles the undated case cleanly. ✔ - **i18n hygiene** — `date_original_label` dropped from all three locales (de/en/es) symmetrically. No dangling key, no orphaned usage. ✔ ### Suggestions (non-blocking) - The drawer still declares `metaDateRaw` as a prop and threads it through purely as the season-word source. That's correct, but a one-word rename or a short comment at the prop site (mirroring the one you added in `DocumentDate.svelte`) would make it obvious to the next reader that `metaDateRaw` is no longer a display field. Minor. Nothing blocks merge. This is the kind of small, honest cleanup I like.
Author
Owner

🏛️ Markus Keller — Application Architect

Verdict: Approved

This is a frontend-only presentation-layer cleanup with no module-boundary, transport, schema, or data-flow implications. Nothing here changes who owns what.

What I checked

  • No backend change — confirmed against the diff. No new/changed Flyway migration, entity, controller, service, endpoint, ErrorCode, or Permission. The metaDateRaw column and its API contract are untouched; only the display of that field is removed. ✔
  • Documentation triggers — I walked my doc-update matrix. None fire: no new route, no new package, no DB change, no new domain term, no auth/upload-flow change, no architectural decision with lasting consequences. The deleted i18n key is not a documented concept. No diagram or ARCHITECTURE/GLOSSARY update is required. ✔
  • Layer integrity — data still flows server → component via props (metaDateRaw arrives in the drawer's $props() and is forwarded as raw). No client-side fetch introduced, no boundary crossed. ✔
  • Accidental complexity removed, not added — dropping the showRaw boolean flag and the derived showRawLine reduces the component's surface. The remaining raw → seasonFromRaw coupling is a single, well-named, documented path. That's the right level of abstraction; I would not split it further.

Note (not a blocker)

The data model now has a column (metaDateRaw) whose only surviving consumer is a season-word derivation. That's a deliberate product decision, not architectural debt — the PR body documents it and the issue (#710) is the source of truth. No ADR needed; this is reversible UI scope, not a structural choice.

Approved.

## 🏛️ Markus Keller — Application Architect **Verdict: ✅ Approved** This is a frontend-only presentation-layer cleanup with no module-boundary, transport, schema, or data-flow implications. Nothing here changes who owns what. ### What I checked - **No backend change** — confirmed against the diff. No new/changed Flyway migration, entity, controller, service, endpoint, `ErrorCode`, or `Permission`. The `metaDateRaw` column and its API contract are untouched; only the *display* of that field is removed. ✔ - **Documentation triggers** — I walked my doc-update matrix. None fire: no new route, no new package, no DB change, no new domain term, no auth/upload-flow change, no architectural decision with lasting consequences. The deleted i18n key is not a documented concept. No diagram or ARCHITECTURE/GLOSSARY update is required. ✔ - **Layer integrity** — data still flows server → component via props (`metaDateRaw` arrives in the drawer's `$props()` and is forwarded as `raw`). No client-side fetch introduced, no boundary crossed. ✔ - **Accidental complexity removed, not added** — dropping the `showRaw` boolean flag and the derived `showRawLine` *reduces* the component's surface. The remaining `raw → seasonFromRaw` coupling is a single, well-named, documented path. That's the right level of abstraction; I would not split it further. ### Note (not a blocker) The data model now has a column (`metaDateRaw`) whose *only* surviving consumer is a season-word derivation. That's a deliberate product decision, not architectural debt — the PR body documents it and the issue (#710) is the source of truth. No ADR needed; this is reversible UI scope, not a structural choice. Approved.
Author
Owner

🔐 Nora "NullX" Steiner — Application Security Engineer

Verdict: Approved

This PR removes attack surface, it does not add any. From a security standpoint it's a net improvement, and the reasoning in the PR body is sound.

Threat-model analysis

The metaDateRaw cell is untrusted verbatim spreadsheet text — exactly the kind of input I treat as hostile. Before this PR it was reflected into the DOM in three rendered sinks (the DocumentDate secondary line and the WhoWhenSection "Originaltext" block). All three were rendered via Svelte's default {...} interpolation, which HTML-escapes — so they were correctly not XSS (CWE-79), but they were still untrusted data on screen.

After this PR the only surviving consumer of raw is seasonFromRaw(raw) in documentDate.ts. I checked that function's contract via the surrounding comment and the formatter docstring: it matches the raw cell against a fixed allowlist of German season tokens and emits a localized season word, never the raw string. So there is no path by which metaDateRaw reaches the DOM anymore — escaped or otherwise. ✔

  • No new sink introduced; the removed <input type="hidden" name="metaDateRaw"> also closes a (benign but real) mass-assignment-style round-trip where verbatim import text was re-submitted on every edit. Removing it is good hygiene. ✔
  • DocumentMetadataDrawer guard tightening — narrowing {#if documentDate || metaDateRaw} to {#if documentDate} is a small but genuine data-exposure fix: previously a raw-only/undated document would enter the DocumentDate branch; now it renders a neutral em-dash and the raw text never leaks. ✔
  • No {@html}, no innerHTML, no eval anywhere in the diff. ✔

Regression coverage (educational note, not a blocker)

The two deleted DocumentDate tests included the XSS-escaping assertion (<img src=x onerror=...> rendered inert). Deleting them is justified — the sink they guarded no longer exists, so the test would be testing nothing. The new WhoWhenSection test (input[name="metaDateRaw"] is absent) and the new drawer test (raw text never surfaces) are good replacements that lock in the "no round-trip / no leak" property. If you want belt-and-suspenders, a single assertion in DocumentDate.svelte.test.ts that a malicious raw value produces no visible text would permanently document "raw is never a display sink" — but it's optional given the season path is allowlist-bound.

Approved. Good defensive cleanup.

## 🔐 Nora "NullX" Steiner — Application Security Engineer **Verdict: ✅ Approved** This PR *removes* attack surface, it does not add any. From a security standpoint it's a net improvement, and the reasoning in the PR body is sound. ### Threat-model analysis The `metaDateRaw` cell is **untrusted verbatim spreadsheet text** — exactly the kind of input I treat as hostile. Before this PR it was reflected into the DOM in three rendered sinks (the `DocumentDate` secondary line and the `WhoWhenSection` "Originaltext" block). All three were rendered via Svelte's default `{...}` interpolation, which HTML-escapes — so they were *correctly* not XSS (CWE-79), but they were still untrusted data on screen. After this PR the **only** surviving consumer of `raw` is `seasonFromRaw(raw)` in `documentDate.ts`. I checked that function's contract via the surrounding comment and the formatter docstring: it matches the raw cell against a **fixed allowlist of German season tokens** and emits a *localized season word*, never the raw string. So there is no path by which `metaDateRaw` reaches the DOM anymore — escaped or otherwise. ✔ - **No new sink introduced**; the removed `<input type="hidden" name="metaDateRaw">` also closes a (benign but real) mass-assignment-style round-trip where verbatim import text was re-submitted on every edit. Removing it is good hygiene. ✔ - **`DocumentMetadataDrawer` guard tightening** — narrowing `{#if documentDate || metaDateRaw}` to `{#if documentDate}` is a small but genuine data-exposure fix: previously a raw-only/undated document would enter the `DocumentDate` branch; now it renders a neutral em-dash and the raw text never leaks. ✔ - **No `{@html}`, no `innerHTML`, no `eval`** anywhere in the diff. ✔ ### Regression coverage (educational note, not a blocker) The two deleted `DocumentDate` tests included the XSS-escaping assertion (`<img src=x onerror=...>` rendered inert). Deleting them is *justified* — the sink they guarded no longer exists, so the test would be testing nothing. The new `WhoWhenSection` test (`input[name="metaDateRaw"]` is absent) and the new drawer test (raw text never surfaces) are good replacements that lock in the "no round-trip / no leak" property. If you want belt-and-suspenders, a single assertion in `DocumentDate.svelte.test.ts` that a malicious `raw` value produces **no** visible text would permanently document "raw is never a display sink" — but it's optional given the season path is allowlist-bound. Approved. Good defensive cleanup.
Author
Owner

🧪 Sara Holt — Senior QA Engineer

Verdict: ⚠️ Approved with concerns

The test changes are well-structured and the deletions are defensible, but I want to be precise about what coverage moved where, and flag one assertion pattern worth double-checking.

What's good

  • Tests changed with the code, asserting absence — the flipped WhoWhenSection test asserts both [data-testid="who-when-raw"] and input[name="metaDateRaw"] are toBeNull(). That's the right regression guard for the core acceptance criterion ("no round-trip"), and it reads as a sentence. ✔
  • New drawer test for the edge case'shows an em-dash and never the raw cell for an undated, raw-only document' covers exactly the boundary the guard change introduced (undated + raw-only). One behavior, clear name. ✔
  • Deleting the two DocumentDate tests is justified — they asserted on a DOM sink that no longer exists. Keeping them would be testing a deleted feature. DAY/MONTH label coverage is retained. ✔

Concerns (please verify, not necessarily blocking)

  1. getByText(...).not.toBeInTheDocument() for absence. In the new drawer test and the WhoWhenSection test you mix two styles: document.querySelector(...) + toBeNull() (robust for absence) and page.getByText('Sommer 1916').not.toBeInTheDocument(). The locator-based negative assertion is the right vitest-browser idiom, but absence assertions are the classic spot for false greens — if the text were rendered slightly differently (e.g. wrapped, or with surrounding whitespace) a positive assertion would catch it but a negative one silently passes. Since these are browser-project (Playwright) tests that only run in CI, please confirm CI is green on this branch before merge — I can't validate them locally and won't trust "it compiles."

  2. Em-dash assertion is broad. dashTexts.length > 0 over all dd, p elements proves an em-dash exists somewhere, not that it's the date cell specifically. It's the same pattern as the existing undated test so it's consistent, but it would pass even if the date cell rendered raw text and some other field happened to show "—". Scoping the assertion to the date <dd> would make the failure mode unambiguous. Minor — the companion Sommer 1916-is-absent assertion mostly covers the gap.

Coverage note

Net branch coverage should be neutral-to-slightly-down (you removed the showRawLine derived and its branches along with their tests). That's expected and fine — you deleted logic, not left it untested. Just don't let a coverage-ratchet gate flag this as a regression.

No blockers. Confirm CI green on the browser project and I'm happy.

## 🧪 Sara Holt — Senior QA Engineer **Verdict: ⚠️ Approved with concerns** The test changes are well-structured and the deletions are *defensible*, but I want to be precise about what coverage moved where, and flag one assertion pattern worth double-checking. ### What's good - **Tests changed with the code, asserting absence** — the flipped `WhoWhenSection` test asserts both `[data-testid="who-when-raw"]` and `input[name="metaDateRaw"]` are `toBeNull()`. That's the right regression guard for the core acceptance criterion ("no round-trip"), and it reads as a sentence. ✔ - **New drawer test for the edge case** — `'shows an em-dash and never the raw cell for an undated, raw-only document'` covers exactly the boundary the guard change introduced (undated + raw-only). One behavior, clear name. ✔ - **Deleting the two `DocumentDate` tests is justified** — they asserted on a DOM sink that no longer exists. Keeping them would be testing a deleted feature. DAY/MONTH label coverage is retained. ✔ ### Concerns (please verify, not necessarily blocking) 1. **`getByText(...).not.toBeInTheDocument()` for absence.** In the new drawer test and the `WhoWhenSection` test you mix two styles: `document.querySelector(...)` + `toBeNull()` (robust for absence) and `page.getByText('Sommer 1916').not.toBeInTheDocument()`. The locator-based negative assertion is the right vitest-browser idiom, but absence assertions are the classic spot for **false greens** — if the text were rendered slightly differently (e.g. wrapped, or with surrounding whitespace) a positive assertion would catch it but a negative one silently passes. Since these are browser-project (Playwright) tests that only run in CI, please confirm CI is green on this branch before merge — I can't validate them locally and won't trust "it compiles." 2. **Em-dash assertion is broad.** `dashTexts.length > 0` over all `dd, p` elements proves *an* em-dash exists somewhere, not that it's the date cell specifically. It's the same pattern as the existing undated test so it's consistent, but it would pass even if the date cell rendered raw text *and* some other field happened to show "—". Scoping the assertion to the date `<dd>` would make the failure mode unambiguous. Minor — the companion `Sommer 1916`-is-absent assertion mostly covers the gap. ### Coverage note Net branch coverage should be neutral-to-slightly-down (you removed the `showRawLine` derived and its branches along with their tests). That's expected and fine — you deleted logic, not left it untested. Just don't let a coverage-ratchet gate flag this as a regression. No blockers. Confirm CI green on the browser project and I'm happy.
Author
Owner

🎨 Leonie Voss — UX & Accessibility Lead

Verdict: Approved

Removing the "Originaltext:" line is the right UX call. For our dual audience — and especially the 60+ transcribers — a verbatim spreadsheet cell shown next to a clean, formatted date is noise: two competing date representations create exactly the "which one is real?" hesitation that Nielsen's aesthetic and minimalist design heuristic warns against. The screen now states the date once, honestly.

What I checked

  • No loss of meaningful information — the season word (e.g. "Sommer 1916") is still derived and shown via seasonFromRaw; users don't lose the human-readable approximate date. Only the redundant raw echo is gone. ✔
  • Undated state stays accessibleDocumentDate.svelte retains the neutral undated chip (#668): the calendar-with-question glyph is decorative (aria-hidden), and the visible "Datum unbekannt" text is the real, announced cue. Removing the raw line did not touch that pattern. An absence (undated) is still presented as neutral metadata, never as an error — no red/amber. ✔
  • Em-dash fallback — the drawer now shows "—" for undated/raw-only documents. That's a clear, conventional "no value" indicator and is consistent with the location field's existing ?? '—'. ✔
  • List vs. detail consistencyDocumentRow already suppressed the raw line (showRaw={false}); now that the line is gone everywhere, list rows and detail views are consistent rather than divergent. That's a small IA win — same date representation everywhere. ✔
  • No contrast/touch-target/responsive impact — nothing interactive added or removed; no color, sizing, or breakpoint changes. ✔

Suggestion (non-blocking)

None of real substance. If anything, this is a model "less is more" cleanup. I'd only note for the changelog/issue that editors transcribing handwritten dates now rely entirely on the structured precision controls — which is the intended workflow, and better than the old dual display.

Approved with enthusiasm.

## 🎨 Leonie Voss — UX & Accessibility Lead **Verdict: ✅ Approved** Removing the "Originaltext:" line is the right UX call. For our dual audience — and especially the 60+ transcribers — a verbatim spreadsheet cell shown next to a clean, formatted date is *noise*: two competing date representations create exactly the "which one is real?" hesitation that Nielsen's *aesthetic and minimalist design* heuristic warns against. The screen now states the date once, honestly. ### What I checked - **No loss of meaningful information** — the season word (e.g. "Sommer 1916") is still derived and shown via `seasonFromRaw`; users don't lose the human-readable approximate date. Only the redundant raw echo is gone. ✔ - **Undated state stays accessible** — `DocumentDate.svelte` retains the neutral undated chip (#668): the calendar-with-question glyph is decorative (`aria-hidden`), and the visible "Datum unbekannt" text is the real, announced cue. Removing the raw line did not touch that pattern. An absence (undated) is still presented as neutral metadata, never as an error — no red/amber. ✔ - **Em-dash fallback** — the drawer now shows "—" for undated/raw-only documents. That's a clear, conventional "no value" indicator and is consistent with the location field's existing `?? '—'`. ✔ - **List vs. detail consistency** — `DocumentRow` already suppressed the raw line (`showRaw={false}`); now that the line is gone everywhere, list rows and detail views are *consistent* rather than divergent. That's a small IA win — same date representation everywhere. ✔ - **No contrast/touch-target/responsive impact** — nothing interactive added or removed; no color, sizing, or breakpoint changes. ✔ ### Suggestion (non-blocking) None of real substance. If anything, this is a model "less is more" cleanup. I'd only note for the changelog/issue that editors transcribing handwritten dates now rely entirely on the structured precision controls — which is the intended workflow, and better than the old dual display. Approved with enthusiasm.
Author
Owner

📋 "Elicit" — Requirements Engineer / Business Analyst (Brownfield)

Verdict: Approved

This PR has an unusually clean requirements trace, which is exactly what I look for in a brownfield cleanup. It closes #710 (the source of truth), states the why in user terms, and is explicit about scope and non-scope.

Requirements assessment

  • Clear, testable change — the requirement reduces to: "The system shall not display or re-submit the metaDateRaw cell anywhere in the UI, while continuing to derive the season word from it internally." Both halves are observable and are covered by tests (raw-line/hidden-input absent; season path retained). ✔
  • Scope discipline / no gold-plating — the PR resists the tempting over-reach of also deleting the backend column or the season-word feature. It removes exactly the confusing visible element and nothing more. The "two roles, only the visible one removed" framing in the body is a textbook scope statement. ✔
  • Non-functional impact considered — security (no new sink), a11y (undated state preserved), and i18n (key removed in all three locales) are all addressed. That's the NFR checklist passing without me having to prompt it.

Open questions / ambiguity (worth confirming, not blocking)

  1. Future of metaDateRaw as data. The column now exists solely to feed a season word. That's fine today, but it's a latent requirements question: is metaDateRaw ever expected to become user-visible again (e.g. an admin/provenance view), or is it permanently an internal derivation input? If the latter, consider a follow-up issue to document that decision in the glossary so a future editor doesn't "rediscover" the field and re-surface it. Logging this as OQ-710-01 — not a blocker.
  2. Editor workflow expectation. With the verbatim cell gone from the edit form, editors transcribing ambiguous handwritten dates now have only the structured precision controls. The issue implies this is intended; just confirm there's no scenario where an editor needed to see the original import text to decide the structured value. If that need exists, it's a separate (provenance) requirement, not a regression of this one.

Both items are clarifications for the backlog, not defects. The change as specified is complete, testable, and well-scoped. Approved.

## 📋 "Elicit" — Requirements Engineer / Business Analyst (Brownfield) **Verdict: ✅ Approved** This PR has an unusually clean requirements trace, which is exactly what I look for in a brownfield cleanup. It closes #710 (the source of truth), states the *why* in user terms, and is explicit about scope and non-scope. ### Requirements assessment - **Clear, testable change** — the requirement reduces to: *"The system shall not display or re-submit the `metaDateRaw` cell anywhere in the UI, while continuing to derive the season word from it internally."* Both halves are observable and are covered by tests (raw-line/hidden-input absent; season path retained). ✔ - **Scope discipline / no gold-plating** — the PR resists the tempting over-reach of also deleting the backend column or the season-word feature. It removes *exactly* the confusing visible element and nothing more. The "two roles, only the visible one removed" framing in the body is a textbook scope statement. ✔ - **Non-functional impact considered** — security (no new sink), a11y (undated state preserved), and i18n (key removed in all three locales) are all addressed. That's the NFR checklist passing without me having to prompt it. ### Open questions / ambiguity (worth confirming, not blocking) 1. **Future of `metaDateRaw` as data.** The column now exists solely to feed a season word. That's fine *today*, but it's a latent requirements question: is `metaDateRaw` ever expected to become user-visible again (e.g. an admin/provenance view), or is it permanently an internal derivation input? If the latter, consider a follow-up issue to document that decision in the glossary so a future editor doesn't "rediscover" the field and re-surface it. Logging this as **OQ-710-01** — not a blocker. 2. **Editor workflow expectation.** With the verbatim cell gone from the edit form, editors transcribing ambiguous handwritten dates now have *only* the structured precision controls. The issue implies this is intended; just confirm there's no scenario where an editor needed to *see* the original import text to decide the structured value. If that need exists, it's a separate (provenance) requirement, not a regression of this one. Both items are clarifications for the backlog, not defects. The change as specified is complete, testable, and well-scoped. Approved.
Author
Owner

⚙️ Tobias Wendt — DevOps & Platform Engineer

Verdict: Approved (LGTM)

Nothing in my domain to flag. I checked the diff for anything operational and found none:

  • No infrastructure files touched — no docker-compose*.yml, no Caddyfile, no CI workflow, no Dockerfile, no env-var or secret changes. ✔
  • No new service, port, volume, or external integration.
  • No backend build/runtime impact — frontend-only; no pom.xml, no new dependency, no migration that would run on deploy. ✔
  • No deployment or rollback risk — this is a pure presentation-layer deletion. Worst case is a stale-cache mismatch on the static bundle, which the normal frontend build/deploy already handles.

The only thing that runs in CI for this PR is the frontend lint/check/unit + the browser-project component tests. As long as the pipeline is green (the new browser tests only execute in CI), there's nothing here that affects the VPS, the Compose stack, or the monthly bill.

Approved — no operational concerns.

## ⚙️ Tobias Wendt — DevOps & Platform Engineer **Verdict: ✅ Approved (LGTM)** Nothing in my domain to flag. I checked the diff for anything operational and found none: - **No infrastructure files touched** — no `docker-compose*.yml`, no Caddyfile, no CI workflow, no Dockerfile, no env-var or secret changes. ✔ - **No new service, port, volume, or external integration.** ✔ - **No backend build/runtime impact** — frontend-only; no `pom.xml`, no new dependency, no migration that would run on deploy. ✔ - **No deployment or rollback risk** — this is a pure presentation-layer deletion. Worst case is a stale-cache mismatch on the static bundle, which the normal frontend build/deploy already handles. The only thing that runs in CI for this PR is the frontend lint/check/unit + the browser-project component tests. As long as the pipeline is green (the new browser tests only execute in CI), there's nothing here that affects the VPS, the Compose stack, or the monthly bill. Approved — no operational concerns.
marcel merged commit 8a1cc2d1f0 into main 2026-06-01 20:35:40 +02:00
marcel deleted branch feat/issue-710-remove-originaltext 2026-06-01 20:35:40 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#712