Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/130-mongo-mapping-nativecap-geo-manifest-and-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

161 lines
11 KiB
Plaintext

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<MongoTypeMetadataDescriptor> 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: * <p>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