diff --git a/cdc-service/src/main/java/com/xtrmetl/cdc/spi/PostgresDebeziumCdcSource.java b/cdc-service/src/main/java/com/xtrmetl/cdc/spi/PostgresDebeziumCdcSource.java
index dcc0e653..2009c738 100644
--- a/cdc-service/src/main/java/com/xtrmetl/cdc/spi/PostgresDebeziumCdcSource.java
+++ b/cdc-service/src/main/java/com/xtrmetl/cdc/spi/PostgresDebeziumCdcSource.java
@@ -11,6 +11,10 @@
/**
* Adapter for the live Debezium PostgreSQL capture path owned by {@link CdcService}.
*
+ *
The live service reads connection and Debezium settings from deployment configuration. Per-call
+ * SPI configuration is therefore intentionally unsupported: callers must pass an empty map so values
+ * such as credentials are never accepted and then silently ignored.
+ *
* {@link #start(Map)} / {@link #stop()} delegate to the service when available so the SPI
* is a real control surface for the supported source type.
*/
@@ -67,13 +71,34 @@ public SourceCapabilities capabilities() {
return new SourceCapabilities("debezium-embedded", Set.of("postgresql"), false);
}
+ /**
+ * Validates the per-call configuration accepted by this adapter.
+ *
+ * The live PostgreSQL capture service is configured by the deployment, not by this SPI call.
+ * An empty map is therefore the only valid value.
+ *
+ * @param config per-call settings; must be non-null and empty
+ * @throws IllegalArgumentException when {@code config} is null or contains any entry
+ */
@Override
public void validate(Map config) {
if (config == null) {
throw new IllegalArgumentException("config must not be null");
}
+ if (!config.isEmpty()) {
+ throw new IllegalArgumentException(
+ "postgres-debezium uses deployment-owned configuration; per-call config must be empty"
+ );
+ }
}
+ /**
+ * Starts the deployment-configured PostgreSQL CDC service.
+ *
+ * @param config per-call settings; must be non-null and empty
+ * @throws IllegalArgumentException when {@code config} is null or contains any entry
+ * @throws IllegalStateException when the live {@link CdcService} is unavailable
+ */
@Override
public void start(Map config) {
validate(config);
diff --git a/cdc-service/src/test/java/com/xtrmetl/cdc/spi/PostgresDebeziumCdcSourceConfigurationTest.java b/cdc-service/src/test/java/com/xtrmetl/cdc/spi/PostgresDebeziumCdcSourceConfigurationTest.java
new file mode 100644
index 00000000..a65766fa
--- /dev/null
+++ b/cdc-service/src/test/java/com/xtrmetl/cdc/spi/PostgresDebeziumCdcSourceConfigurationTest.java
@@ -0,0 +1,43 @@
+package com.xtrmetl.cdc.spi;
+
+import com.xtrmetl.cdc.service.CdcService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.ObjectProvider;
+
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+/**
+ * Guards the PostgreSQL source SPI against silently ignored per-call configuration.
+ */
+class PostgresDebeziumCdcSourceConfigurationTest {
+
+ @Test
+ void rejectsCallerConfigurationBeforeStartingDeploymentConfiguredService() {
+ CdcService service = mock(CdcService.class);
+ @SuppressWarnings("unchecked")
+ ObjectProvider provider = mock(ObjectProvider.class);
+ when(provider.getIfAvailable()).thenReturn(service);
+ PostgresDebeziumCdcSource source = new PostgresDebeziumCdcSource(provider);
+ String rejectedSecret = "buyer-secret-password-8472";
+
+ IllegalArgumentException failure = assertThrows(
+ IllegalArgumentException.class,
+ () -> source.start(Map.of("database.password", rejectedSecret))
+ );
+
+ assertEquals(
+ "postgres-debezium uses deployment-owned configuration; per-call config must be empty",
+ failure.getMessage()
+ );
+ assertFalse(failure.getMessage().contains(rejectedSecret));
+ assertFalse(failure.getMessage().contains("database.password"));
+ verifyNoInteractions(service);
+ }
+}