Sub-scope 03 (mongo) mapping + nativecap + geo — manifest and negative-space probes revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5 generatedAt=2026-08-29T23:49:32+00:00 cwd=/shared/codebase/clean-architecture-backend-template/src === OWNED FILES === 72953a64190f0f694f89591c80a764b27db54069 main/java/dev/caskeleton/adapter/outbound/mongo/geo/MongoGeoDistance.java 54 944c7b86656ab33af7b42f82e15c8d735db13395 main/java/dev/caskeleton/adapter/outbound/mongo/geo/MongoGeoPoint.java 39 214513c7132868faf96e60d6bd0b02a4c221ab2a main/java/dev/caskeleton/adapter/outbound/mongo/geo/MongoGeoQuery.java 43 c437f2e6527dde79d91ad8a964a22a554fa8b1f3 main/java/dev/caskeleton/adapter/outbound/mongo/geo/MongoGeospatialOperations.java 21 bc2dbbfa7e681c4bbb4a59bce60c4a9ffa8bc191 main/java/dev/caskeleton/adapter/outbound/mongo/geo/SpringMongoGeospatialOperations.java 120 767ddc4caec1751d879a90ed4525dc54521d413a main/java/dev/caskeleton/adapter/outbound/mongo/mapping/BigDecimalToDecimal128Converter.java 56 a6670a37afd4c8e0f55063f99e7607b8182b01e4 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/BigIntegerRepresentationConverters.java 96 7c1f34986f59537eb14277537c5e2c56c6ad3cc2 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/Decimal128ToBigDecimalConverter.java 29 5bf3289eef7b7d51fc03f38b7f183af2def725b9 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/DomainIdReadConverter.java 21 65ac609e91d4044dab7a2e599c8271756c96b240 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/DomainIdWriteConverter.java 20 1d11c7523c07489299da5c6e169d3cce9a82daa9 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/LocalDateTimeMappingGuard.java 61 3316ca832683b235c8e9b313afcfb68d271b86cc main/java/dev/caskeleton/adapter/outbound/mongo/mapping/MongoCustomConversionsFactory.java 87 9ff0549795955266fd4ece2368a27e90b2804301 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/MongoMappingConfiguration.java 110 ab6677dcad01cc2e978967061bd71178c0a83838 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/MongoTypeMetadataConfigurer.java 38 d1ed747d5bd36c632d0e5d98806ac53b8dd1513e main/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/LongLivedMongoDocument.java 31 29ddc389b6530a6a6203d78a722a817d0de61f4b main/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/MongoTypeMetadataDescriptor.java 46 1e9b1bb1072a5b0aea37a486cd169fc28040bcbb main/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/MongoTypeMetadataRegistry.java 122 0fa892842fe5233aaf3b381fc3900dc28f2af2e9 main/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/PolicyAwareMongoTypeMapper.java 205 8ddb11c59c6e405aaa119038f35279443891a784 main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/ApprovedMongoNativeOperation.java 67 d39bcca075a57bc14dbe429f6918ae847af36d34 main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/MongoNativeCapabilityGateway.java 14 b83fc163ef8b2bbc96c06869405290edac0b22ac main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/MongoNativeCommandCategory.java 28 5f759fa4c14ccec81b5a421a728552c8f227fd48 main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/MongoNativeOperationPolicy.java 148 a4b61e84e77ad188f521b1d754d673ecfd05851e main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/PolicyAwareMongoNativeGateway.java 46 57693cee88da8503991f42d52cbfef9b9c796aab test/java/dev/caskeleton/adapter/outbound/mongo/geo/MongoGeoPointTest.java 58 e9327b84b30a1262b65d07a9e749826ae60efb90 test/java/dev/caskeleton/adapter/outbound/mongo/mapping/MongoMappingConfigurationTest.java 177 5b93db65a7ab80e91648322ebec0387f9072c834 test/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/PolicyAwareMongoTypeMapperTest.java 118 f1ccfd0e6c231e5c3b77e8c4fc97d86972ab6ec5 test/java/dev/caskeleton/adapter/outbound/mongo/nativecap/PolicyAwareMongoNativeGatewayTest.java 148 production: 23 test: 4 === 8.1 reachability: which of these types a production configuration actually builds === $ git grep -n 'MongoMappingConfiguration\|MongoTypeMetadataConfigurer\|MongoTypeMetadataRegistry\|LocalDateTimeMappingGuard\|MongoCustomConversionsFactory' -- 'adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo' | grep -v '/mapping/' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:13:import dev.caskeleton.adapter.outbound.mongo.mapping.MongoMappingConfiguration; adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java:48:@Import(MongoMappingConfiguration.class) exit=0 $ git grep -n 'SpringMongoGeospatialOperations\|MongoGeospatialOperations' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/geo/' exit=1 $ git grep -n 'MongoNativeCapabilityGateway\|PolicyAwareMongoNativeGateway' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/nativecap/' exit=1 === 8.2 sibling comparison: how the same 'unregistered type' question is answered === $ grep -n 'orElseThrow' -A 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/PolicyAwareMongoTypeMapper.java | sed -n '1,14p' 75: .orElseThrow( 76- () -> 77- new IllegalStateException( 78- "no type metadata policy is registered for " 79- + rawType.getName() 80- + "; a stored document's type metadata outlives the class, so the" 81- + " policy is a decision to record rather than to default")); 82- switch (policy) { 83- case NO_TYPE_METADATA -> { -- 182: .orElseThrow( 183- () -> 184- new MongoSchemaValidationException( 185- MongoFailureContext.schemaMismatch(READ_OPERATION))); exit=0 $ grep -n 'orElse(MongoTypeMetadataPolicy.CLASS_METADATA_ALLOWED)' -B 4 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/PolicyAwareMongoTypeMapper.java 130- Optional descriptor = registry.find(restrictedType); 131- MongoTypeMetadataPolicy policy = 132- descriptor 133- .map(MongoTypeMetadataDescriptor::policy) 134: .orElse(MongoTypeMetadataPolicy.CLASS_METADATA_ALLOWED); exit=0 $ grep -n 'policyFor' -B 2 -A 5 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/mapping/type/MongoTypeMetadataRegistry.java 72- 73- /** The effective policy for a type; unregistered types keep Spring Data's default. */ 74: public MongoTypeMetadataPolicy policyFor(Class documentType) { 75- return find(documentType) 76- .map(MongoTypeMetadataDescriptor::policy) 77- .orElse(MongoTypeMetadataPolicy.CLASS_METADATA_ALLOWED); 78- } 79- exit=0 === 8.2b the D3 gateway's documented sequence versus the checks that exist === $ grep -n 'Runs the design.s stated sequence' -A 4 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/PolicyAwareMongoNativeGateway.java 11: *

Runs the design's stated sequence and stops at the first refusal: registration, capability, 12- * database profile, collection profile, timeout, category, then execution. The audit record carries 13- * the operation id and the outcome and never the BSON arguments — the arguments are the part that 14- * contains data, and an audit trail that leaks data is a liability rather than a control. 15- */ exit=0 $ grep -n 'D3는 raw client escape가 아니다' -A 3 adapter/outbound/persistence-mongo/README.md 65:D3는 raw client escape가 아니다. `PolicyAwareMongoNativeGateway`가 capability → database profile → 66-collection allowlist → operation name → timeout → consistency → result limit → trace → redaction → 67-command category → D4 차단 순서를 고정한다. 68- exit=0 $ grep -n 'throw MongoOperationRejectedException' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/nativecap/MongoNativeOperationPolicy.java 56: throw MongoOperationRejectedException.of( 64: throw MongoOperationRejectedException.of( 75: throw MongoOperationRejectedException.of( 80: throw MongoOperationRejectedException.of( 85: throw MongoOperationRejectedException.of( 92: throw MongoOperationRejectedException.of( exit=0 $ git grep -n 'operation.timeout()\|\.hasBody()' -- 'adapter/outbound/persistence-mongo/src/main' exit=1 $ git grep -n 'operation.maxResults()' -- 'adapter/outbound/persistence-mongo/src/main' exit=1 === 8.3 duplicate mechanism: two result-limit vocabularies === $ git grep -ln 'maxResults()' -- 'adapter/outbound/persistence-mongo/src/main' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/aggregation/PolicyAwareMongoAggregationExecutor.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/query/PolicyAwareMongoQueryBuilder.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/query/budget/MongoBudgetEnforcer.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/reactive/cursor/MongoReactiveCursorPublisher.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/reactive/cursor/MongoResultBudgetTracker.java exit=0 === 8.4 geo: the index precondition and the unit type === $ grep -n 'requireSphereIndex' -A 6 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/geo/SpringMongoGeospatialOperations.java | head -20 49: requireSphereIndex(access.collection(), query.field()); 50- // $nearSphere over a GeoJSON point takes metres and already returns nearest-first, so 51- // no sort stage is needed — and adding one would discard the index-ordered scan. 52- Query near = 53- new Query( 54- Criteria.where(query.field()) 55- .nearSphere(query.center().toGeoJsonPoint()) -- 76: requireSphereIndex(access.collection(), query.field()); 77- Circle circle = 78- new Circle(toPoint(query.center()), query.maxDistance().toSpringDistance()); 79- Query within = 80- new Query(Criteria.where(query.field()).withinSphere(circle)) 81- .limit(query.resultLimit()); 82- return access.rawOperations().find(within, documentType, access.collection()); -- 92: private void requireSphereIndex(String collection, String field) { 93- boolean supported = 94- manifests 95- .find(collection) exit=0 $ grep -n 'toSpringDistance' -A 6 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/geo/MongoGeoDistance.java 39: public Distance toSpringDistance() { 40- return unit == MongoDistanceUnit.KILOMETERS 41- ? new Distance(value, Metrics.KILOMETERS) 42- : new Distance(value / 1000, Metrics.KILOMETERS); 43- } 44- 45- /** The unit a geo distance is expressed in. */ exit=0