CredentialDetector.java
package org.egothor.methodatlas.api;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
/**
* Source of credential candidates for one scanned file.
*
* <p>
* Implementations are deterministic and AI-free: identical input must yield
* identical candidates on every run. Unlike {@link TestDiscovery}, a detector
* does not walk the file tree — the orchestration layer selects files (by mask)
* and presents each as a {@link CredentialScanUnit}.
* </p>
*
* <p>
* Providers are discovered via {@link java.util.ServiceLoader}; each provider JAR
* ships a {@code META-INF/services/org.egothor.methodatlas.api.CredentialDetector}
* registration. An empty provider set is legitimate and disables the feature.
* </p>
*
* @since 4.1.0
*/
public interface CredentialDetector extends Closeable {
/**
* Returns the unique identifier of this detector. Must be unique across all
* detectors on the classpath; the orchestration layer rejects duplicates.
*
* @return non-null, non-empty identifier
*/
String detectorId();
/**
* Configures this detector before the first {@link #detect(CredentialScanUnit)} call.
* The default is a no-op.
*
* @param config runtime configuration; never {@code null}
*/
default void configure(CredentialDetectorConfig config) {
// default: no-op
}
/**
* Scans a single source unit and returns every credential candidate found.
*
* @param unit the file to scan; never {@code null}
* @return candidates in source order; never {@code null}; may be empty
*/
List<CredentialCandidate> detect(CredentialScanUnit unit);
/**
* Returns {@code true} if any prior {@link #detect} call encountered a
* non-fatal error.
*
* @return {@code true} when at least one unit could not be fully processed
*/
boolean hadErrors();
/**
* Releases any resources held by this detector. The default is a no-op.
*
* @throws IOException if releasing a resource fails
*/
@Override
default void close() throws IOException {
// default: no-op
}
}