Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/136-mongo-security-failure-observation-client-probes.txt
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

468 lines
45 KiB
Plaintext

Sub-scope 09 (mongo) security + failure + observation + client - manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T00:22:02+00:00
cwd=/shared/codebase/clean-architecture-backend-template/src
=== OWNED FILES ===
70bb70e58ac29b6c1401715556b3bc999ecdde08 main/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactory.java 122
bd752d8017c85a8a179ec33f6bcac31a191938d2 main/java/dev/caskeleton/adapter/outbound/mongo/failure/DefaultMongoFailureClassifier.java 165
078eb6624daee4e12077317fe7f0f40c1484583f main/java/dev/caskeleton/adapter/outbound/mongo/failure/DefaultMongoFailureTranslator.java 136
42607f5e5692a704b40fb16f8e8deef7bc4eca8d main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoDriverFailureView.java 96
305db8f20852d5d4a5b31e6bd9e5a563113f0a4e main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureClassification.java 84
fa7ee1fdb4d8b87db62636665e163d6efa54ade3 main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureClassifier.java 30
c97bee6755b406ce235b0db2f1ddafd5b43a8ad7 main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureExtractor.java 63
68f7019d768d09bab77c4062d58011f9a3072517 main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailurePhase.java 41
247affc2e97d358eec04ebe39096e749afc74e62 main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureTranslator.java 32
cb66127e79ac161b23cbf8397da1fb23eaf1f2cc main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java 104
d58c2b1109ea4c6d3b37a84048c1baded4c0e23f main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoCommandObservationListener.java 72
6833f38c54a5a82ab91515c7f1706d9436771525 main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java 43
95d47f6c83dfba0486a290c12061062e10e4139a main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java 76
b31b95daae98c9d222b03def13571c20b567fe3b main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationRedactor.java 48
862d03f5a8c6df8a6edf80b61dc19cab616e7004 main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoPoolObservationListener.java 79
da98d619400a5428052ebffb23918ed829b7eedb main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoSdamObservationListener.java 76
1eefc12534906eb0a5fe89f5f3679e5b0154073a main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialReference.java 74
c2630cf7b6e8e81348ab1e38337b9ad2d743ad5e main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialResolver.java 43
07772c4569a6e77a17f172a688c2c9ae385d3ade main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialRotationPolicy.java 50
97e58d6d456edf916972c8cdc6f96f65ad74f605 main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoPrincipalRole.java 63
ff75d970bf3da211faa9ca538dd11ae8834ac76c main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java 54
5966a708bf8282bc8a1d1734978e16caaddf5ee1 main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidator.java 69
7e3139a9e13624b6640938d0cf316819f464386c main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminApproval.java 57
416ae3c05c952d61268619061f066000964c6ec6 main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditPhase.java 21
4ce978358da0817f3f4c89392e3ba2c1f348c717 main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditRecord.java 103
365d9d2a76e8da168df5e4b6c3ae5b444315fc2f main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuthorization.java 58
b0e6c2311cd23484f1694797e6dca247440d245d main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminCommand.java 103
3f7a8e9e0ea5e0921c87ef9d5cd10863acbac1dd main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminGateway.java 155
bb4c1d808aac7a9db42f3faf73fbb848ad4462bc main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminOperation.java 69
2ea0b6961acfdaffa37d6f2c4ed1ae41b407efb1 main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminRuntimeGuard.java 58
c669128d19905192760fa6461e382e803b171466 test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java 155
8cade411549e57554ef2af67d8c4a75d0edc7b8e test/java/dev/caskeleton/adapter/outbound/mongo/failure/DefaultMongoFailureClassifierTest.java 85
31cfe2e045e67d31200371cb577c1027756872e8 test/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureExtractorTest.java 85
c3c0bedd5f340edde465bdae5531be9550b9f16e test/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailurePhaseClassificationTest.java 114
9cd42c63fc963e16f864877619d7bda9f2dbdb71 test/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoNetworkFaultLaneTest.java 206
8fd453d853874984528c4ddfea935bd63c481ed3 test/java/dev/caskeleton/adapter/outbound/mongo/failure/TranslatorCarriesOperationContextTest.java 70
ec8897a4907ed8bfd3209d83beb030d1c5446ce4 test/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConventionTest.java 67
355d56a96e8c76c519b6239bcd39e67f30ccf867 test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialIdentityTest.java 108
64f8ff90b050f7347dd58bf2e7d21e672d5d41a2 test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoProductionSecurityContractTest.java 176
48ddb5c88db513fed1666dea0b712cf6d11615d7 test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityIntegrationLaneTest.java 173
bd76cc9d30bd033639a5911c9f965838c7784ecb test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidatorTest.java 115
3ca3a9db79b2f5ff033b25d659da79850d39c4b2 test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoTlsLaneTest.java 164
9ab88fab1970f5bbdcc009269b0de14188701e21 test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditStateMachineTest.java 250
e080d8c0e10b9ee0999c0170fdd0e2a4457d80cf test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminRuntimeGuardTest.java 117
production: 30
test: 14
production LOC: 2244 total
=== 8.1 reachability: what the auto-configuration builds from these four packages ===
$ grep -n 'ClientSettings\|CredentialResolver\|SecurityProfile\|FailureTranslator\|FailureClassifier\|Observ\|Redactor\|AdminGateway' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java
5:import dev.caskeleton.adapter.outbound.mongo.api.observation.MongoOperationObserver;
6:import dev.caskeleton.adapter.outbound.mongo.failure.DefaultMongoFailureClassifier;
7:import dev.caskeleton.adapter.outbound.mongo.failure.DefaultMongoFailureTranslator;
8:import dev.caskeleton.adapter.outbound.mongo.failure.MongoFailureClassifier;
9:import dev.caskeleton.adapter.outbound.mongo.failure.MongoFailureTranslator;
14:import dev.caskeleton.adapter.outbound.mongo.observation.MicrometerMongoOperationObserver;
85: public MongoFailureClassifier mongoFailureClassifier() {
86: return new DefaultMongoFailureClassifier();
92: public MongoFailureTranslator mongoFailureTranslator(MongoFailureClassifier classifier) {
93: return new DefaultMongoFailureTranslator(classifier);
104: public MongoOperationObserver mongoOperationObserver(ObjectProvider<MeterRegistry> registries) {
107: ? MongoOperationObserver.none()
108: : new MicrometerMongoOperationObserver(registry, "default");
117: MongoFailureTranslator translator,
118: MongoOperationObserver observer) {
298: MongoFailureTranslator translator,
299: MongoOperationObserver observer) {
335: ObjectProvider<dev.caskeleton.adapter.outbound.mongo.security.MongoSecurityProfile>
exit=0
=== 8.1b does the platform actually build the driver client from its own factory? ===
$ git grep -n 'MongoClientSettingsFactory' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactory.java:38:public final class MongoClientSettingsFactory {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactory.java:51: public MongoClientSettingsFactory(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java:28:class MongoClientSettingsFactoryTest {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java:38: new MongoClientSettingsFactory(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java:60: new MongoClientSettingsFactory(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java:74: new MongoClientSettingsFactory(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java:95: new MongoClientSettingsFactory(settings, ACTIVE, resolver(resolved)).create();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java:110: new MongoClientSettingsFactory(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/client/MongoClientSettingsFactoryTest.java:120: new MongoClientSettingsFactory(
exit=0
$ git grep -n 'MongoClientSettings\|MongoClient\b\|MongoClients' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/client/MongoClientSettingsFactory.java'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java:8:import org.springframework.boot.mongodb.autoconfigure.MongoClientSettingsBuilderCustomizer;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java:15: * settings builder, and nothing ever called it. Boot builds the {@code MongoClient} from its own
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java:38: public MongoClientSettingsBuilderCustomizer mongoDriverObservabilityCustomizer(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/MongoNativeCapabilityGateway.java:6: * <p>There is no {@code MongoClient}, {@code MongoDatabase} or {@code MongoCollection<Document>}
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:3:import com.mongodb.MongoClientSettings;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:26: public MongoClientSettings.Builder apply(MongoClientSettings.Builder builder) {
exit=0
$ git grep -rn 'MongoClientSettingsFactory\|MongoCredentialResolver' -- '../app-bootstrap' '../adapter' 2>/dev/null | grep -v persistence-mongo | head
exit=0
=== 8.1c are the driver observability listeners ever installed? ===
$ git grep -n 'MongoDriverObservabilityConfiguration' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java:3:import dev.caskeleton.adapter.outbound.mongo.observation.MongoDriverObservabilityConfiguration;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java:14: * <p>{@link MongoDriverObservabilityConfiguration} could add command, SDAM and pool listeners to a
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java:45: MongoDriverObservabilityConfiguration observability =
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java:46: new MongoDriverObservabilityConfiguration(registry, profile);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:14:public final class MongoDriverObservabilityConfiguration {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:20: public MongoDriverObservabilityConfiguration(MeterRegistry registry, String mongoProfile) {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityWiringTest.java:19: * <p>{@code MongoDriverObservabilityConfiguration} could attach command, SDAM and pool listeners to
exit=0
$ git grep -n 'MongoCommandObservationListener\|MongoSdamObservationListener\|MongoPoolObservationListener' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/observation/'
exit=1
$ git grep -n 'addCommandListener\|addClusterListener\|addConnectionPoolListener' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:28: builder.addCommandListener(new MongoCommandObservationListener(registry, mongoProfile));
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:31: cluster.addClusterListener(new MongoSdamObservationListener(registry, mongoProfile)));
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:34: pool.addConnectionPoolListener(
exit=0
=== 8.1d is the security profile validator called at startup? ===
$ git grep -n 'MongoSecurityProfileValidator\|MongoSecurityProfile\b\|requireDistinctCredentials' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:335: ObjectProvider<dev.caskeleton.adapter.outbound.mongo.security.MongoSecurityProfile>
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:9:import dev.caskeleton.adapter.outbound.mongo.security.MongoSecurityProfile;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:10:import dev.caskeleton.adapter.outbound.mongo.security.MongoSecurityProfileValidator;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:28: private final MongoSecurityProfile runtimeSecurity;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:41: MongoSecurityProfile runtimeSecurity,
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:62: new MongoSecurityProfileValidator().validate(runtimeSecurity);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:117: new MongoSecurityProfileValidator()
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java:118: .requireDistinctCredentials(runtimeSecurity.credential(), admin));
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialReference.java:46: * MongoSecurityProfileValidator#requireDistinctCredentials}, is always called with a runtime role
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:13:public record MongoSecurityProfile(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:20: public MongoSecurityProfile {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:27: public static MongoSecurityProfile production(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:29: return new MongoSecurityProfile(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:38: public static MongoSecurityProfile production(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:40: return new MongoSecurityProfile(true, true, true, credential, grantedPrivileges);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:44: public static MongoSecurityProfile local(MongoCredentialReference credential) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfile.java:45: return new MongoSecurityProfile(false, false, false, credential, Set.of());
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidator.java:14:public final class MongoSecurityProfileValidator {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidator.java:21: public void validate(MongoSecurityProfile profile) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidator.java:57: public void requireDistinctCredentials(
exit=0
$ git grep -n 'MongoCredentialRotationPolicy\|validateRotation' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoClientGenerationRegistry.java:5:import dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialRotationPolicy;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoClientGenerationRegistry.java:31: private final MongoCredentialRotationPolicy rotationPolicy;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoClientGenerationRegistry.java:35: public MongoClientGenerationRegistry(MongoCredentialRotationPolicy rotationPolicy, Clock clock) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoClientGenerationRegistry.java:68: rotationPolicy.validateRotation(existing.credential(), replacement);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:417: dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialRotationPolicy.class)
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:419: dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialRotationPolicy rotationPolicy,
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialReference.java:51: * MongoCredentialRotationPolicy} always knew that: it compares roles on its own line, right after
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialRotationPolicy.java:14:public record MongoCredentialRotationPolicy(Duration drainTimeout, boolean failClosedOnOverlap) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialRotationPolicy.java:16: public MongoCredentialRotationPolicy {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialRotationPolicy.java:24: public static MongoCredentialRotationPolicy standard() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialRotationPolicy.java:25: return new MongoCredentialRotationPolicy(Duration.ofSeconds(30), true);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialRotationPolicy.java:34: public void validateRotation(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoClientGenerationConcurrencyTest.java:8:import dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialRotationPolicy;
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoClientGenerationConcurrencyTest.java:43: new MongoClientGenerationRegistry(MongoCredentialRotationPolicy.standard(), FIXED);
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformPropertiesTest.java:13:import dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialRotationPolicy;
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformPropertiesTest.java:136: MongoCredentialRotationPolicy.standard(),
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformPropertiesTest.java:156: MongoCredentialRotationPolicy.standard(),
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/RotationOrderingTest.java:8:import dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialRotationPolicy;
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/RotationOrderingTest.java:41: new MongoClientGenerationRegistry(MongoCredentialRotationPolicy.standard(), FIXED);
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialIdentityTest.java:21: * <p>{@code MongoCredentialRotationPolicy} is the counter-evidence that the role was never meant to
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialIdentityTest.java:90: new MongoCredentialRotationPolicy(java.time.Duration.ofSeconds(30), true)
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialIdentityTest.java:91: .validateRotation(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidatorTest.java:101: MongoCredentialRotationPolicy policy = MongoCredentialRotationPolicy.standard();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidatorTest.java:105: assertThatThrownBy(() -> policy.validateRotation(current, current))
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/MongoSecurityProfileValidatorTest.java:109: policy.validateRotation(
exit=0
=== 8.2 the observation allowlist: enforced by code, or only asserted by a test? ===
$ git grep -n 'requireAllowed\|allowedTagNames\|forbiddenTagNames\|MongoObservationConvention' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/search/MongoSearchQuery.java:48: public void requireAllowedPaths(Set<String> allowedPaths) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/sharding/ShardAwareQueryValidator.java:59: public MongoRoutingClassification requireAllowedRead(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/aggregation/MongoAggregationProfile.java:86: public void requireAllowed(MongoAggregationStageDescriptor descriptor) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/aggregation/PolicyAwareMongoAggregationExecutor.java:49: plan.stages().forEach(profile::requireAllowed);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:40: public MongoObservationConvention convention() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoDriverObservabilityConfiguration.java:41: return MongoObservationConvention.standard();
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java:17:public final class MongoObservationConvention {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java:44: private MongoObservationConvention() {}
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java:47: public static MongoObservationConvention standard() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java:48: return new MongoObservationConvention();
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java:52: public Set<String> allowedTagNames() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java:57: public Set<String> forbiddenTagNames() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoObservationConvention.java:66: public void requireAllowed(String tagName) {
exit=0
$ grep -n 'Tags.of' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/*.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java:46: Tags.of(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java:72: this.outcomeTags = Tags.of("result", "unknown", "failureCategory", "none");
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java:77: outcomeTags = Tags.of("result", outcome.name(), "failureCategory", "none");
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java:83: Tags.of(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoCommandObservationListener.java:63: Tags.of(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoPoolObservationListener.java:40: Tags tags = Tags.of("mongoProfile", mongoProfile);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoPoolObservationListener.java:60: .tags(Tags.of("mongoProfile", mongoProfile, "failureCategory", event.getReason().name()))
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoSdamObservationListener.java:46: .tags(Tags.of("mongoProfile", mongoProfile))
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MongoSdamObservationListener.java:61: .tags(Tags.of("mongoProfile", mongoProfile))
exit=0
$ git grep -n 'redactor.describe\|\.describe(' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/api/error/MongoPersistenceException.java:24: summary + " [" + Objects.requireNonNull(failureContext, "failureContext").describe() + "]");
exit=0
=== 8.2b the admin gateway's two audit paths ===
$ grep -n 'private void audit' -A 12 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminGateway.java
127: private void audit(MongoAdminAuditRecord record) {
128- try {
129- auditSink.accept(record);
130- } catch (RuntimeException sinkFailed) {
131- throw MongoOperationRejectedException.of(
132- "admin.audit",
133- "the admin audit sink refused the "
134- + record.phase()
135- + " record; an administrative operation that cannot be audited does not run");
136- }
137- }
138-
139- /**
exit=0
$ grep -n 'public void dryRun' -A 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminGateway.java
145: public void dryRun(MongoAdminOperation operation, String target, String operator, String reason) {
146- authorization.require(operation);
147- auditSink.accept(
148- MongoAdminAuditRecord.dryRun(operation, target, operator, reason, clock.instant()));
149- }
150-
151- /** The guard this gateway was constructed under. */
152- public MongoAdminRuntimeGuard guard() {
153- return guard;
exit=0
=== 8.2c traceId ===
$ grep -rn 'traceId' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/api/observation/MongoOperationObservation.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/api/observation/MongoOperationObservation.java:22: String traceId();
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java:91: public String traceId() {
exit=0
$ git grep -n 'traceId()' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/api/observation/MongoOperationObservation.java:22: String traceId();
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/api/observation/NoOpMongoOperationObserver.java:42: public String traceId() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/imperative/DefaultMongoImperativeExecutor.java:129: observation.failure(translated.failureContext().withTraceId(observation.traceId()));
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/observation/MicrometerMongoOperationObserver.java:91: public String traceId() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/reactive/DefaultReactiveMongoExecutor.java:169: observation.failure(translated.failureContext().withTraceId(observation.traceId()));
exit=0
=== 8.3 duplicate / unused mechanisms ===
$ git grep -n 'unrecognisedServerCode\|MongoFailureClassification.nonRetryable\|classify(failure)' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/DefaultMongoFailureClassifier.java:139: return MongoFailureClassification.nonRetryable(category);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureClassification.java:57: public static MongoFailureClassification nonRetryable(MongoFailureCategory category) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureClassification.java:70: public static MongoFailureClassification unrecognisedServerCode() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureClassifier.java:28: return classify(failure);
exit=0
$ git grep -n 'MongoAdminAuditRecord.applied\|adminGatewayAllowed\|MongoAdminApproval.of' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminApproval.java:31: public static MongoAdminApproval of(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditRecord.java:98: public static MongoAdminAuditRecord applied(
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminRuntimeGuard.java:55: public boolean adminGatewayAllowed() {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditStateMachineTest.java:138: MongoAdminApproval.of(rehearsal, "approver", NOW.plus(Duration.ofMinutes(10)));
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditStateMachineTest.java:157: MongoAdminApproval.of(approved, "approver", NOW.plusSeconds(600)),
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditStateMachineTest.java:167: MongoAdminApproval approval = MongoAdminApproval.of(command, "approver", NOW.plusSeconds(600));
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminAuditStateMachineTest.java:187: MongoAdminApproval.of(command, "approver", NOW.minusSeconds(1)),
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminRuntimeGuardTest.java:48: assertThat(guard.adminGatewayAllowed()).isTrue();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminRuntimeGuardTest.java:101: MongoAdminAuditRecord.applied(
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/security/admin/MongoAdminRuntimeGuardTest.java:106: MongoAdminAuditRecord.applied(
exit=0
$ git grep -n 'MongoFailureExtractor' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureExtractor.java:21:public final class MongoFailureExtractor {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/MongoFailureExtractor.java:26: private MongoFailureExtractor() {}
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringMongoTransactionSessionFactory.java:22:import dev.caskeleton.adapter.outbound.mongo.failure.MongoFailureExtractor;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringMongoTransactionSessionFactory.java:225: MongoDriverFailureView view = MongoFailureExtractor.viewOf(failure).orElse(null);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringReactiveMongoTransactionSessionFactory.java:21:import dev.caskeleton.adapter.outbound.mongo.failure.MongoFailureExtractor;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringReactiveMongoTransactionSessionFactory.java:176: MongoDriverFailureView view = MongoFailureExtractor.viewOf(failure).orElse(null);
exit=0
$ git grep -n 'DefaultMongoFailureTranslator.standard\|new DefaultMongoFailureTranslator\|new DefaultMongoFailureClassifier' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:86: return new DefaultMongoFailureClassifier();
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:93: return new DefaultMongoFailureTranslator(classifier);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/DefaultMongoFailureTranslator.java:46: public static DefaultMongoFailureTranslator standard() {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/failure/DefaultMongoFailureTranslator.java:47: return new DefaultMongoFailureTranslator(new DefaultMongoFailureClassifier());
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringMongoTransactionSessionFactory.java:52: this(template, consistency, new DefaultMongoFailureClassifier());
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringReactiveMongoTransactionSessionFactory.java:53: this(template, consistency, new DefaultMongoFailureClassifier());
exit=0
=== 8.4 lane / documentation drift ===
$ grep -n 'lane(' adapter/outbound/persistence-mongo/build.gradle
107: lane('mongoReplicaSetTest') {
113: lane('mongoFailoverTest') {
119: lane('mongoMigrationTest') {
125: lane('mongoCompatibilityTest') {
130: lane('mongoSecurityIntegrationTest') {
139: lane('mongoPerformanceTest') {
exit=0
$ grep -n 'mongodb-security-integration\|mongodb-failover' adapter/outbound/persistence-mongo/build.gradle
96: 'mongodb-failover',
99: 'mongodb-security-integration'
114: tag = 'mongodb-failover'
131: tag = 'mongodb-security-integration'
exit=0
=== 8.1e REPO-WIDE: who builds the MongoClient, and is the platform factory reachable? ===
$ git grep -rn 'MongoClientSettingsFactory' -- . | grep -v 'adapter/outbound/persistence-mongo/src'
exit=1
$ git grep -rln 'MongoCredentialResolver' -- . | grep -v 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/CLAUDE.md
exit=0
$ git grep -rn 'spring.data.mongodb.uri\|spring.mongodb.uri' -- . | head -20
adapter/outbound/persistence-mongo/README.md:37:spring.data.mongodb.uri=mongodb://localhost:27017/portfolio
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/MongoPersistenceSettings.java:10: * own standard {@code spring.mongodb.uri} (owned by Spring Boot's {@code MongoProperties}), which
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/security/MongoCredentialResolver.java:11: * spring.mongodb.uri}, which is an ordinary property — in configuration, in the image and in every
exit=0
$ cat adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoDriverObservabilityAutoConfiguration.java
package dev.caskeleton.adapter.outbound.mongo.autoconfigure;
import dev.caskeleton.adapter.outbound.mongo.observation.MongoDriverObservabilityConfiguration;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.mongodb.autoconfigure.MongoClientSettingsBuilderCustomizer;
import org.springframework.context.annotation.Bean;
/**
* Attaches the driver's observation listeners to the client Boot builds.
*
* <p>{@link MongoDriverObservabilityConfiguration} could add command, SDAM and pool listeners to a
* settings builder, and nothing ever called it. Boot builds the {@code MongoClient} from its own
* customizers, so the listeners were a method with no caller: the pool-checkout, server-selection
* and primary-change metrics the operations documentation refers to were never emitted.
*
* <p>Separate from {@code MongoPlatformAutoConfiguration} because it is conditional on something
* else — a {@link MeterRegistry}. A listener with nowhere to publish costs work on every command,
* so a deployment without metrics gets no listeners rather than silent ones.
*
* <p>These tag by driver event. The platform's own observation tags by operation. The two measure
* different things on purpose, and neither is derived from the other, so a command appears once in
* each rather than twice in one.
*/
@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(
prefix = "ca-skeleton.persistence-mongo",
name = "enabled",
havingValue = "true")
public class MongoDriverObservabilityAutoConfiguration {
/** The customizer Boot applies when it builds the client. */
@Bean
@ConditionalOnBean(MeterRegistry.class)
@ConditionalOnMissingBean(name = "mongoDriverObservabilityCustomizer")
public MongoClientSettingsBuilderCustomizer mongoDriverObservabilityCustomizer(
MeterRegistry registry,
org.springframework.beans.factory.ObjectProvider<MongoPlatformSettings> properties) {
String profile =
properties.getIfAvailable(MongoPlatformSettings::empty).profiles().keySet().stream()
.findFirst()
.orElse("default");
MongoDriverObservabilityConfiguration observability =
new MongoDriverObservabilityConfiguration(registry, profile);
return observability::apply;
}
}
exit=0
$ sed -n '325,375p' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java
* first transaction.
*
* <p>Conditional on a {@link MongoTopologyProbe} bean, because the check is about the server this
* deployment actually talks to, and only a composition root knows how to reach it.
*/
@Bean
@ConditionalOnBean(MongoTopologyProbe.class)
public InitializingBean mongoPlatformStartupCheck(
MongoPlatformSettings properties,
MongoTopologyProbe probe,
ObjectProvider<dev.caskeleton.adapter.outbound.mongo.security.MongoSecurityProfile>
runtimeSecurity,
ObjectProvider<dev.caskeleton.adapter.outbound.mongo.security.MongoCredentialReference>
adminCredential,
ObjectProvider<dev.caskeleton.adapter.outbound.mongo.api.schema.MongoSchemaVersionRange>
schemaVersionRange) {
return () -> {
properties.validate();
var security = runtimeSecurity.getIfAvailable();
var admin = adminCredential.getIfAvailable();
var versions = schemaVersionRange.getIfAvailable();
if (security == null || admin == null || versions == null) {
// Fail closed rather than validate a subset. A partial startup check reports success for
// the parts nobody supplied, which is the shape the missing wiring already had.
throw new IllegalStateException(
"the Mongo platform is enabled and a topology probe is present, but the security"
+ " profile, admin credential reference or schema version range is not configured;"
+ " the startup validator cannot answer with only part of its inputs");
}
new MongoStartupValidator(
properties,
probe,
security,
admin,
// From settings, not literals. These were `true, true`, which told the validator that
// transactions and change streams were both wanted whatever the deployment had
// configured — and then validated the topology against that invented answer.
properties.transactions(),
properties.changeStreams(),
versions)
.validate();
};
}
/**
* Refuses a platform that is on with no way to look at the server it talks to (MNG-INT-003).
*
* <p>{@code mongoPlatformStartupCheck} above is conditioned on a {@link MongoTopologyProbe},
* which is right — the check is about the live server, and only a composition root knows how to
* reach it. But a condition is also an exit: a deployment that enables the platform and supplies
* no probe got no validation at all, silently, and not supplying a bean is exactly what an
exit=0
$ sed -n '55,70p;110,125p' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java
/**
* Runs every startup check.
*
* @throws MongoOperationRejectedException naming the first failed condition
*/
public void validate() {
properties.validate();
new MongoSecurityProfileValidator().validate(runtimeSecurity);
requireDeclaredTopologyMatchesReality();
requireCapabilitiesForEnabledFeatures();
requireDistinctAdminCredential();
requireSupportedSchemaRange();
}
private void requireDeclaredTopologyMatchesReality() {
properties
}
}
private void requireDistinctAdminCredential() {
Optional.ofNullable(adminCredential)
.ifPresent(
admin ->
new MongoSecurityProfileValidator()
.requireDistinctCredentials(runtimeSecurity.credential(), admin));
}
private void requireSupportedSchemaRange() {
if (schemaVersionRange.minimumSupported().compareTo(schemaVersionRange.current()) > 0) {
throw MongoOperationRejectedException.of(
"startup.schema", "the configured schema version range is inverted");
}
exit=0
=== 8.1f the four AutoConfiguration entries this leaf registers ===
$ cat adapter/outbound/persistence-mongo/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
dev.caskeleton.adapter.outbound.mongo.MongoRootAutoConfiguration
exit=0