Umsetzung von Meilenstein M7
This commit is contained in:
@@ -30,6 +30,7 @@ import de.gecheckt.pdf.umbenenner.application.config.RuntimeConfiguration;
|
||||
import de.gecheckt.pdf.umbenenner.application.config.startup.StartConfiguration;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunOutcome;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.AiContentSensitivity;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.AiInvocationPort;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.ClockPort;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.ConfigurationPort;
|
||||
@@ -204,7 +205,7 @@ public class BootstrapRunner {
|
||||
this.schemaInitPortFactory = SqliteSchemaInitializationAdapter::new;
|
||||
this.useCaseFactory = (startConfig, lock) -> {
|
||||
// Extract runtime configuration from startup configuration
|
||||
RuntimeConfiguration runtimeConfig = new RuntimeConfiguration(startConfig.maxPages());
|
||||
RuntimeConfiguration runtimeConfig = new RuntimeConfiguration(startConfig.maxPages(), startConfig.maxRetriesTransient(), resolveAiContentSensitivity(startConfig.logAiSensitive()));
|
||||
|
||||
String jdbcUrl = buildJdbcUrl(startConfig);
|
||||
FingerprintPort fingerprintPort = new Sha256FingerprintAdapter();
|
||||
@@ -218,7 +219,9 @@ public class BootstrapRunner {
|
||||
TargetFolderPort targetFolderPort = new FilesystemTargetFolderAdapter(startConfig.targetFolder());
|
||||
TargetFileCopyPort targetFileCopyPort = new FilesystemTargetFileCopyAdapter(startConfig.targetFolder());
|
||||
DocumentProcessingCoordinator documentProcessingCoordinator =
|
||||
new DocumentProcessingCoordinator(documentRecordRepository, processingAttemptRepository, unitOfWorkPort, targetFolderPort, targetFileCopyPort, coordinatorLogger);
|
||||
new DocumentProcessingCoordinator(documentRecordRepository, processingAttemptRepository,
|
||||
unitOfWorkPort, targetFolderPort, targetFileCopyPort, coordinatorLogger,
|
||||
startConfig.maxRetriesTransient());
|
||||
|
||||
// Wire AI naming pipeline
|
||||
AiInvocationPort aiInvocationPort = new OpenAiHttpAdapter(startConfig);
|
||||
@@ -408,6 +411,23 @@ public class BootstrapRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the {@link AiContentSensitivity} decision from the raw {@code log.ai.sensitive}
|
||||
* configuration flag.
|
||||
* <p>
|
||||
* The safe default is {@link AiContentSensitivity#PROTECT_SENSITIVE_CONTENT}.
|
||||
* {@link AiContentSensitivity#LOG_SENSITIVE_CONTENT} is only produced when
|
||||
* {@code logAiSensitive} is explicitly {@code true}.
|
||||
*
|
||||
* @param logAiSensitive the parsed boolean value of the {@code log.ai.sensitive} property
|
||||
* @return the appropriate sensitivity decision; never {@code null}
|
||||
*/
|
||||
static AiContentSensitivity resolveAiContentSensitivity(boolean logAiSensitive) {
|
||||
return logAiSensitive
|
||||
? AiContentSensitivity.LOG_SENSITIVE_CONTENT
|
||||
: AiContentSensitivity.PROTECT_SENSITIVE_CONTENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the JDBC URL for the SQLite database from the configured file path.
|
||||
*
|
||||
|
||||
@@ -7,6 +7,7 @@ import de.gecheckt.pdf.umbenenner.adapter.out.configuration.ConfigurationLoading
|
||||
import de.gecheckt.pdf.umbenenner.application.config.startup.StartConfiguration;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunOutcome;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.AiContentSensitivity;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.ConfigurationPort;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.DocumentPersistenceException;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.PersistenceSchemaInitializationPort;
|
||||
@@ -60,7 +61,8 @@ class BootstrapRunnerEdgeCasesTest {
|
||||
null, // null runtimeLockFile
|
||||
tempDir.resolve("logs"),
|
||||
"INFO",
|
||||
"test-key"
|
||||
"test-key",
|
||||
false
|
||||
);
|
||||
|
||||
AtomicReference<Path> capturedLockPath = new AtomicReference<>();
|
||||
@@ -106,7 +108,8 @@ class BootstrapRunnerEdgeCasesTest {
|
||||
tempDir.resolve("lock.lock"),
|
||||
tempDir.resolve("logs"),
|
||||
"INFO",
|
||||
"test-key"
|
||||
"test-key",
|
||||
false
|
||||
);
|
||||
|
||||
String jdbcUrl = BootstrapRunner.buildJdbcUrl(config);
|
||||
@@ -132,7 +135,8 @@ class BootstrapRunnerEdgeCasesTest {
|
||||
tempDir.resolve("lock.lock"),
|
||||
tempDir.resolve("logs"),
|
||||
"INFO",
|
||||
"test-key"
|
||||
"test-key",
|
||||
false
|
||||
);
|
||||
|
||||
String jdbcUrl = BootstrapRunner.buildJdbcUrl(config);
|
||||
@@ -159,7 +163,8 @@ class BootstrapRunnerEdgeCasesTest {
|
||||
tempDir.resolve("lock.lock"),
|
||||
tempDir.resolve("logs"),
|
||||
"INFO",
|
||||
"test-key"
|
||||
"test-key",
|
||||
false
|
||||
);
|
||||
|
||||
// Verify BatchRunContext can be created (used internally by BootstrapRunner)
|
||||
@@ -223,7 +228,7 @@ class BootstrapRunnerEdgeCasesTest {
|
||||
return new StartConfiguration(sourceDir, targetDir, dbFile,
|
||||
URI.create("https://api.example.com"), "gpt-4", 30, 3, 100, 50000,
|
||||
promptFile, tempDir.resolve("lock.lock"), tempDir.resolve("logs"),
|
||||
"INFO", "key");
|
||||
"INFO", "key", false);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -319,6 +324,24 @@ class BootstrapRunnerEdgeCasesTest {
|
||||
assertEquals(1, runner.run(), "LOCK_UNAVAILABLE outcome should map to exit code 1");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// AI Content Sensitivity Resolution
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void resolveAiContentSensitivity_falseYieldsProtectSensitiveContent() {
|
||||
assertEquals(AiContentSensitivity.PROTECT_SENSITIVE_CONTENT,
|
||||
BootstrapRunner.resolveAiContentSensitivity(false),
|
||||
"logAiSensitive=false must resolve to PROTECT_SENSITIVE_CONTENT (safe default)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveAiContentSensitivity_trueYieldsLogSensitiveContent() {
|
||||
assertEquals(AiContentSensitivity.LOG_SENSITIVE_CONTENT,
|
||||
BootstrapRunner.resolveAiContentSensitivity(true),
|
||||
"logAiSensitive=true must resolve to LOG_SENSITIVE_CONTENT");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Mocks
|
||||
// =========================================================================
|
||||
@@ -364,7 +387,8 @@ class BootstrapRunnerEdgeCasesTest {
|
||||
tempDir.resolve("lock.lock"),
|
||||
tempDir.resolve("logs"),
|
||||
"INFO",
|
||||
"test-api-key"
|
||||
"test-api-key",
|
||||
false
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to create mock configuration", e);
|
||||
|
||||
@@ -186,7 +186,8 @@ class BootstrapRunnerTest {
|
||||
Paths.get(""), // empty – simulates unconfigured runtime.lock.file
|
||||
tempDir.resolve("logs"),
|
||||
"INFO",
|
||||
"test-key"
|
||||
"test-key",
|
||||
false
|
||||
);
|
||||
|
||||
AtomicReference<Path> capturedLockPath = new AtomicReference<>();
|
||||
@@ -319,7 +320,8 @@ class BootstrapRunnerTest {
|
||||
tempDir.resolve("lock.lock"),
|
||||
tempDir.resolve("logs"),
|
||||
"INFO",
|
||||
"test-api-key"
|
||||
"test-api-key",
|
||||
false
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to create mock configuration", e);
|
||||
|
||||
Reference in New Issue
Block a user