Fix Issue #13: Warnschwelle für max.title.length auf 10–39 angehoben

Neue Warnschwellen: 10–39 Warnung (Absender benötigt 15–20 Zeichen),
40–99 unkritisch, 100–120 Warnung (verschlüsselte Volumes). Tests,
Validator-Implementierungen, Smoke-Tests und Docs konsistent angepasst.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-23 08:11:36 +02:00
parent c61108fe1b
commit 5d0e2c90bd
7 changed files with 50 additions and 20 deletions
+3 -3
View File
@@ -286,9 +286,9 @@ Validierungsregeln für `max.title.length` (Feld „Max. Titellänge (Zeichen)"
| Kein Wert / leer | Fehler Pflichtfeld, Konfiguration nicht lauffähig | | Kein Wert / leer | Fehler Pflichtfeld, Konfiguration nicht lauffähig |
| Keine Ganzzahl (z. B. „abc") | Fehler ungültiger Typ | | Keine Ganzzahl (z. B. „abc") | Fehler ungültiger Typ |
| Kleiner als 10 | Fehler Minimum ist 10 Zeichen | | Kleiner als 10 | Fehler Minimum ist 10 Zeichen |
| 10 19 | Warnung Titellänge unter 20 Zeichen ist für die meisten Dokumente nicht empfohlen | | 10 39 | Warnung Titellänge unter 40 Zeichen KI-Ergebnisse können unvollständig sein, da Absender allein bereits 1520 Zeichen benötigt |
| 20 99 | Normaler Betrieb, keine Meldung | | 40 99 | Normaler Betrieb, keine Meldung |
| 100 120 | Warnung Dateiname wird sehr lang, Kompatibilität mit verschlüsselten Volumes prüfen | | 100 120 | Warnung Hohe Titellänge Kompatibilität mit verschlüsselten Volumes prüfen |
| Größer als 120 | Fehler überschreitet sicheres Limit für verschlüsselte Volumes | | Größer als 120 | Fehler überschreitet sicheres Limit für verschlüsselte Volumes |
Warnungen verhindern das Speichern nicht. Fehler markieren den Stand als nicht lauffähig; Speichern ist dennoch erlaubt, jedoch erscheint ein deutlicher Hinweis im Meldungsbereich. Warnungen verhindern das Speichern nicht. Fehler markieren den Stand als nicht lauffähig; Speichern ist dennoch erlaubt, jedoch erscheint ein deutlicher Hinweis im Meldungsbereich.
+3 -3
View File
@@ -59,9 +59,9 @@ für den Basistitel (143 18 = 125, mit Puffer auf 120 gerundet).
| Keine Ganzzahl (z. B. „abc", „1.5") | Fehler | Ungültiger Typ, Start wird abgebrochen | | Keine Ganzzahl (z. B. „abc", „1.5") | Fehler | Ungültiger Typ, Start wird abgebrochen |
| < 1 | Fehler | Wert muss positiv sein, Start wird abgebrochen | | < 1 | Fehler | Wert muss positiv sein, Start wird abgebrochen |
| 19 | Fehler | Minimum ist 10 Zeichen, Start wird abgebrochen | | 19 | Fehler | Minimum ist 10 Zeichen, Start wird abgebrochen |
| 1019 | Warnung | „Titellänge unter 20 Zeichen ist für die meisten Dokumente nicht empfohlen" | | 1039 | Warnung | „Titellänge unter 40 Zeichen KI-Ergebnisse können unvollständig sein, da Absender allein bereits 1520 Zeichen benötigt" |
| 2099 | OK | Normaler Betrieb, keine Meldung | | 4099 | OK | Normaler Betrieb, keine Meldung |
| 100120 | Warnung | „Hohe Titellänge Dateiname wird sehr lang, Kompatibilität mit verschlüsselten Volumes prüfen" | | 100120 | Warnung | „Hohe Titellänge Kompatibilität mit verschlüsselten Volumes prüfen" |
| > 120 | Fehler | Überschreitet sicheres Limit für verschlüsselte Synology-Volumes, Start wird abgebrochen | | > 120 | Fehler | Überschreitet sicheres Limit für verschlüsselte Synology-Volumes, Start wird abgebrochen |
--- ---
@@ -514,7 +514,7 @@ class GuiEditorValidationSmokeTest {
} }
/** /**
* Smoke test: a value in the lower warning band (10..19) produces a field finding that is * Smoke test: a value in the lower warning band (10..39) produces a field finding that is
* not marked as ERROR. * not marked as ERROR.
* *
* @throws Exception if the FX thread task fails or times out * @throws Exception if the FX thread task fails or times out
@@ -230,7 +230,7 @@ public class StartConfigurationValidator {
* </ul> * </ul>
* Non-blocking warnings (logged but accepted): * Non-blocking warnings (logged but accepted):
* <ul> * <ul>
* <li>{@code 10 <= value <= 19}: low-range warning (below the usual minimum)</li> * <li>{@code 10 <= value <= 39}: low-range warning (AI results may be incomplete)</li>
* <li>{@code 100 <= value <= 120}: high-range warning (filename compatibility with * <li>{@code 100 <= value <= 120}: high-range warning (filename compatibility with
* encrypted Synology volumes)</li> * encrypted Synology volumes)</li>
* </ul> * </ul>
@@ -249,9 +249,9 @@ public class StartConfigurationValidator {
+ "). Überschreitet sicheres Limit für verschlüsselte Synology-Volumes."); + "). Überschreitet sicheres Limit für verschlüsselte Synology-Volumes.");
return; return;
} }
if (value <= 19) { if (value <= 39) {
LOG.warn("Titellänge {} unter 20 Zeichen ist für die meisten Dokumente nicht empfohlen", LOG.warn("Titellänge {} unter 40 Zeichen KI-Ergebnisse können unvollständig sein, "
value); + "da Absender allein bereits 1520 Zeichen benötigt", value);
} else if (value >= 100) { } else if (value >= 100) {
LOG.warn("Titellänge {} ist hoch Kompatibilität mit verschlüsselten Volumes " LOG.warn("Titellänge {} ist hoch Kompatibilität mit verschlüsselten Volumes "
+ "(Limit ~143 Zeichen inkl. Datumspräfix) prüfen", + "(Limit ~143 Zeichen inkl. Datumspräfix) prüfen",
@@ -991,7 +991,21 @@ class StartConfigurationValidatorTest {
void validate_succeedsForLowWarnRange() throws Exception { void validate_succeedsForLowWarnRange() throws Exception {
StartConfiguration config = buildValidConfigWithMaxTitleLength(15); StartConfiguration config = buildValidConfigWithMaxTitleLength(15);
assertDoesNotThrow(() -> validator.validate(config), assertDoesNotThrow(() -> validator.validate(config),
"Werte im Bereich 10..19 sind zulässig (nur Warnung im Log)"); "Werte im Bereich 10..39 sind zulässig (nur Warnung im Log)");
}
@Test
void validate_succeedsForLowWarnRangeUpperBoundary() throws Exception {
StartConfiguration config = buildValidConfigWithMaxTitleLength(39);
assertDoesNotThrow(() -> validator.validate(config),
"Wert 39 ist zulässig (nur Warnung im Log)");
}
@Test
void validate_succeedsForNormalRangeLowerBoundary() throws Exception {
StartConfiguration config = buildValidConfigWithMaxTitleLength(40);
assertDoesNotThrow(() -> validator.validate(config),
"Wert 40 ist unkritisch (kein Log-Warn)");
} }
@Test @Test
@@ -68,7 +68,7 @@ public class EditorConfigurationValidator {
// Grenzen für die maximale Basistitel-Länge. // Grenzen für die maximale Basistitel-Länge.
private static final int TITLE_LENGTH_MIN = 10; private static final int TITLE_LENGTH_MIN = 10;
private static final int TITLE_LENGTH_MAX = 120; private static final int TITLE_LENGTH_MAX = 120;
private static final int TITLE_LENGTH_LOW_WARN_THRESHOLD = 20; private static final int TITLE_LENGTH_LOW_WARN_THRESHOLD = 40;
private static final int TITLE_LENGTH_HIGH_WARN_THRESHOLD = 100; private static final int TITLE_LENGTH_HIGH_WARN_THRESHOLD = 100;
/** /**
@@ -237,10 +237,10 @@ public class EditorConfigurationValidator {
* <li>&lt; {@value #TITLE_LENGTH_MIN}: Fehler (Minimum)</li> * <li>&lt; {@value #TITLE_LENGTH_MIN}: Fehler (Minimum)</li>
* <li>&gt; {@value #TITLE_LENGTH_MAX}: Fehler (sicheres Maximum für verschlüsselte Volumes)</li> * <li>&gt; {@value #TITLE_LENGTH_MAX}: Fehler (sicheres Maximum für verschlüsselte Volumes)</li>
* <li>{@value #TITLE_LENGTH_MIN}{@value #TITLE_LENGTH_LOW_WARN_THRESHOLD} (einschließlich * <li>{@value #TITLE_LENGTH_MIN}{@value #TITLE_LENGTH_LOW_WARN_THRESHOLD} (einschließlich
* 19): Warnung (unter 20 Zeichen selten empfehlenswert)</li> * 39): Warnung (unter 40 Zeichen KI-Ergebnisse können unvollständig sein)</li>
* <li>&ge; {@value #TITLE_LENGTH_HIGH_WARN_THRESHOLD}: Warnung (Kompatibilitätsrisiko * <li>&ge; {@value #TITLE_LENGTH_HIGH_WARN_THRESHOLD}: Warnung (Kompatibilitätsrisiko
* mit verschlüsselten Volumes)</li> * mit verschlüsselten Volumes)</li>
* <li>andernfalls (2099): kein Befund</li> * <li>andernfalls (4099): kein Befund</li>
* </ul> * </ul>
* *
* @param rawValue Rohwert aus dem Editor; nie {@code null} * @param rawValue Rohwert aus dem Editor; nie {@code null}
@@ -275,17 +275,17 @@ public class EditorConfigurationValidator {
} }
if (value < TITLE_LENGTH_LOW_WARN_THRESHOLD) { if (value < TITLE_LENGTH_LOW_WARN_THRESHOLD) {
findings.add(EditorValidationFinding.warning(FIELD_MAX_TITLE_LENGTH, findings.add(EditorValidationFinding.warning(FIELD_MAX_TITLE_LENGTH,
"Titellänge unter " + TITLE_LENGTH_LOW_WARN_THRESHOLD "Titellänge unter 40 Zeichen KI-Ergebnisse können unvollständig sein, "
+ " Zeichen ist für die meisten Dokumente nicht empfohlen (aktuell: " + "da Absender allein bereits 1520 Zeichen benötigt (aktuell: "
+ value + ").")); + value + ")."));
return; return;
} }
if (value >= TITLE_LENGTH_HIGH_WARN_THRESHOLD) { if (value >= TITLE_LENGTH_HIGH_WARN_THRESHOLD) {
findings.add(EditorValidationFinding.warning(FIELD_MAX_TITLE_LENGTH, findings.add(EditorValidationFinding.warning(FIELD_MAX_TITLE_LENGTH,
"Hohe Titellänge: Kompatibilität mit verschlüsselten Volumes prüfen " "Hohe Titellänge Kompatibilität mit verschlüsselten Volumes prüfen "
+ "(aktuell: " + value + ").")); + "(aktuell: " + value + ")."));
} }
// 2099: unkritisch, kein Befund // 4099: unkritisch, kein Befund
} }
// ========================================================================= // =========================================================================
@@ -591,9 +591,25 @@ class EditorConfigurationValidatorTest {
} }
@Test @Test
void validate_maxTitleLength_twenty_producesNoFinding() { void validate_maxTitleLength_twenty_producesWarning() {
EditorValidationReport report = validator.validate(inputWithMaxTitleLength("20")); EditorValidationReport report = validator.validate(inputWithMaxTitleLength("20"));
assertThat(report.findingsFor(EditorConfigurationValidator.FIELD_MAX_TITLE_LENGTH))
.anyMatch(f -> f.severity() == EditorValidationSeverity.WARNING);
}
@Test
void validate_maxTitleLength_thirtyNine_producesWarning() {
EditorValidationReport report = validator.validate(inputWithMaxTitleLength("39"));
assertThat(report.findingsFor(EditorConfigurationValidator.FIELD_MAX_TITLE_LENGTH))
.anyMatch(f -> f.severity() == EditorValidationSeverity.WARNING);
}
@Test
void validate_maxTitleLength_forty_producesNoFinding() {
EditorValidationReport report = validator.validate(inputWithMaxTitleLength("40"));
assertThat(report.findingsFor(EditorConfigurationValidator.FIELD_MAX_TITLE_LENGTH)) assertThat(report.findingsFor(EditorConfigurationValidator.FIELD_MAX_TITLE_LENGTH))
.isEmpty(); .isEmpty();
} }