Sub-scope 07 (mongo) schema + migration - manifest and negative-space probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T00:04:41+00:00
cwd=/shared/codebase/clean-architecture-backend-template/src

=== OWNED FILES ===
0466ca15110d4251cef0759b3c1383b73ee59232 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLedger.java 187
f9170f8288edeab3487c7918852a78f2a6137f65 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLock.java 180
a3a6d5ecf2ecbd4d05b17e5bf2b03118d60feb8c main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigration.java 30
769ec5d10816627ba8e887f2f8de8d80826c61c5 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationCheckpoint.java 44
4682c0cd8dda0b15365ce585b41c65f4067d9125 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationChecksum.java 30
80296f59836963b7e108804211efec12a42ef373 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationContext.java 81
47af881f0b4ef203e17c26baff47cd92bd23661f main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationHeartbeat.java 32
a1f751aefed77a211c0990095170257e9fb54f81 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationId.java 33
65a2e6cab8f1582372f07b2b042cd38685dde18c main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLedger.java 54
ca21debac1dd694789d075b0d32508302272145e main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLock.java 49
5db2ea1cddf4d82df9b0d81893a5487d4c1b53ea main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationPostcondition.java 21
83f020725259fc9c634d69e2f6c91ccae34b6551 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationPrecondition.java 20
5718f2152bd32c4aa22fb2edbbbd7941903aa0ac main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationResult.java 58
b79d234a93e4e9f7755bbfa266f93de6da464f72 main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationRunner.java 161
8de0ca45f1d4317726a7b9271810da2e969b4ab5 main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockChangeUnitView.java 29
113c564352c7f7739c1fdc4d731c8cff51d6dcd6 main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockLedgerAdapter.java 77
34f128ba5191d0ed026da420e6652cb7699089ee main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockLockAdapter.java 72
40127b9342e69c7d7f0f0ad13c690144038bee63 main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockMigrationConfiguration.java 40
d9bd3c5db0a9dd35cc4a8412cd7c45135ff9fe96 main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockMongoMigrationAdapter.java 33
b61b21deb96608b84e28577476043652325e90a7 main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexApplyPolicy.java 49
3070de52719edfb8b0a22c82feef8557a310de3e main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDescriptorView.java 57
3a2396275b191162a19c8073a9cb77795374d826 main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiff.java 55
dece468ed334df72d050e849a5982443fc0c8efe main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngine.java 79
4d8e976dac5191cec7a3024bb4d384bdbc988b72 main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexRetirementPlan.java 60
be34f2f9c81f314bf7433217da7f4000f0b7238f main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexRetirementState.java 52
f35defc38fa8521c97413c658cffe9d9b6d75e7f main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoCollectionManifest.java 107
6e00339723a4bc7d58a00ff90aa39e844b5af38b main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoIndexDirection.java 42
20ba2c85f7b762c226c1dc067e998694f146e3b6 main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoIndexKey.java 20
3a1533d193354efb63ab7d6e12f57152671dfdde main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoIndexManifest.java 243
6ffafda63defa8aa39638518e729030dd44680df main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoManifestRegistry.java 87
e5000ec35e83b27805e4d3b51ba6c288f2501109 main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoMetadataOwnership.java 30
6c07172745f15eabc446b1a16f119dfa148ff814 main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoSchemaManifest.java 79
0fde15eab0dc7e0382f9b13afe40296b0c7c9f21 main/java/dev/caskeleton/adapter/outbound/mongo/schema/model/EmbeddedCollectionDescriptor.java 60
b4eb96dda1f12b4b90504998cd08202c4101b631 main/java/dev/caskeleton/adapter/outbound/mongo/schema/model/MongoBinaryFieldDescriptor.java 32
cc6e4463f03567a521a5c36d8c88e1e5375a87f6 main/java/dev/caskeleton/adapter/outbound/mongo/schema/model/MongoDocumentModelManifest.java 156
e186785b79e639218b1157b75d48e8de93f98f76 main/java/dev/caskeleton/adapter/outbound/mongo/schema/model/MongoDocumentModelValidator.java 88
8c91b34f914b3e8c3e2708ba4855d86cf99505f1 main/java/dev/caskeleton/adapter/outbound/mongo/schema/model/MongoDocumentSizeBudget.java 47
cf1dd7adbdc171ab8b2cadb190ef74739029017e main/java/dev/caskeleton/adapter/outbound/mongo/schema/model/MongoReferenceDescriptor.java 39
6c589c888ef8f9f7427ff00b3dafd643c28afea7 main/java/dev/caskeleton/adapter/outbound/mongo/schema/model/MongoReferenceLifecycle.java 20
786b5e19d229fc84d2aba1c02a91b5e2615fa633 main/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoExpirationAccessPolicy.java 38
2bee1ae545855880eb2165d2551ef57902722b63 main/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoTtlIndexDescriptor.java 38
d554d62f7ff110406764d95352bc623dba491bf2 main/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoTtlPolicy.java 55
5bf375305d37971eaf43ff3e13d49efab6613138 main/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoTtlPolicyValidator.java 94
9bac323540839409b6b14bac4b649afe39968277 main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidationAction.java 26
8d305f8383dd15bf5245f27a1215c4f57d0be522 main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidationLevel.java 21
7da0133d082e8a1f5d9eca37d0de84fe39fc2a37 main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicy.java 102
56cfc5a4826661d1cdcbe669b171cdd99d8f42c9 main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorDescriptor.java 36
03b2f002c9c6dccc0fd91910c7a0b79ea1a13b60 main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorDiff.java 31
34ac7d7480bdd093f00188d1a63753f79f1839b7 main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorDiffEngine.java 50
5dcc5125ed688ba9a84e5950279d766540fe9bae test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationFencingTest.java 238
8de780e56da2c069cf8ee25f34dc4ecac9d5e525 test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java 357
be3f250a150cf77231ef1c63bc8a6ebc0a7b4d5f test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationRunnerTest.java 161
8aab71567e0f5df28a12445d2ef5cc73ff9bdff5 test/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockMongoMigrationAdapterTest.java 118
45b9b78653d63943d63432e55ab835b56135d4b4 test/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngineTest.java 112
e25a040a6f5fa9960e64b8eb484fdf04237cd2a1 test/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoManifestRegistryTest.java 110
095780bb7e5f55eb5a153c69920d6f6d17bf7024 test/java/dev/caskeleton/adapter/outbound/mongo/schema/model/MongoDocumentModelValidatorTest.java 95
ee2cd514b9cb28705cd83a09d1e11810fee6171a test/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoTtlPolicyValidatorTest.java 61
4282df2da997e11d1783655d3915970ffa24bcee test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java 74

production: 49
test: 9
production LOC:   3124 total

=== 8.1 reachability: what the auto-configuration builds from schema/migration ===
$ grep -n 'schema\.\|migration\.\|Manifest\|Migration\|IndexDiff\|Validator' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java
4:import dev.caskeleton.adapter.outbound.mongo.api.mapping.MongoTypeRepresentationManifest;
315:  public MongoTypeRepresentationManifest mongoPlatformTypeRepresentationManifest() {
316:    return MongoTypeRepresentationManifest.standard();
339:      ObjectProvider<dev.caskeleton.adapter.outbound.mongo.api.schema.MongoSchemaVersionRange>
354:      new MongoStartupValidator(
exit=0

$ git grep -ln 'schema.manifest\|schema.index\|schema.model\|schema.ttl\|schema.validation' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/schema/'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/encryption/qe/MongoEncryptionMetadataOwnership.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/search/MongoSearchIndexDescriptor.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/shared/MongoTenantManifestValidator.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/api/error/MongoSchemaValidationException.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/geo/SpringMongoGeospatialOperations.java
exit=0

$ git grep -ln 'mongo.migration' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/migration/'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCheckpointStore.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java
exit=0

=== 8.1b who consults the apply policies ===
$ git grep -n 'MongoIndexApplyPolicy\|requireRuntimeApplyAllowed' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexApplyPolicy.java:14:public enum MongoIndexApplyPolicy {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexApplyPolicy.java:38:  public void requireRuntimeApplyAllowed(String collection) {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngineTest.java:77:    assertThat(MongoIndexApplyPolicy.REPORT_ONLY.runtimeMayApply()).isFalse();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngineTest.java:78:    assertThatThrownBy(() -> MongoIndexApplyPolicy.REPORT_ONLY.requireRuntimeApplyAllowed("orders"))
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngineTest.java:81:    assertThat(MongoIndexApplyPolicy.APPLY.runtimeMayApply()).isTrue();
exit=0

$ git grep -n 'MongoValidatorApplyPolicy' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicy.java:23:public final class MongoValidatorApplyPolicy {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicy.java:37:  private MongoValidatorApplyPolicy(String serverVersion) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicy.java:42:  public static MongoValidatorApplyPolicy forServer(String serverVersion) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicy.java:43:    return new MongoValidatorApplyPolicy(Objects.requireNonNull(serverVersion, "serverVersion"));
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/api/capability/MongoServerVersionTest.java:6:import dev.caskeleton.adapter.outbound.mongo.schema.validation.MongoValidatorApplyPolicy;
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/api/capability/MongoServerVersionTest.java:24:    assertThat(MongoValidatorApplyPolicy.forServer("8.0.4").certifiedLane())
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/api/capability/MongoServerVersionTest.java:27:    assertThat(MongoValidatorApplyPolicy.forServer("7.0.28").certifiedLane()).isTrue();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/api/capability/MongoServerVersionTest.java:33:    assertThat(MongoValidatorApplyPolicy.forServer("6.0.19").certifiedLane()).isFalse();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/api/capability/MongoServerVersionTest.java:34:    assertThat(MongoValidatorApplyPolicy.forServer("8.1.0").certifiedLane()).isFalse();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/api/capability/MongoServerVersionTest.java:40:    assertThat(MongoValidatorApplyPolicy.forServer("unknown").certifiedLane())
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java:14:class MongoValidatorApplyPolicyTest {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java:18:    MongoValidatorApplyPolicy policy = MongoValidatorApplyPolicy.forServer("8.0");
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java:28:                MongoValidatorApplyPolicy.forServer("7.0")
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java:35:    MongoValidatorApplyPolicy policy = MongoValidatorApplyPolicy.forServer("8.0");
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java:44:    assertThat(MongoValidatorApplyPolicy.forServer("8.0").runtimeMayApply()).isFalse();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java:55:                MongoValidatorApplyPolicy.forServer("8.0")
exit=0

$ git grep -n 'new MongoIndexDiffEngine\|new MongoValidatorDiffEngine' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngineTest.java:18:  private final MongoIndexDiffEngine engine = new MongoIndexDiffEngine();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/schema/validation/MongoValidatorApplyPolicyTest.java:64:        new MongoValidatorDiffEngine()
exit=0

$ git grep -n 'MongoManifestRegistry' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/geo/SpringMongoGeospatialOperations.java:10:import dev.caskeleton.adapter.outbound.mongo.schema.manifest.MongoManifestRegistry;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/geo/SpringMongoGeospatialOperations.java:29:  private final MongoManifestRegistry manifests;
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/geo/SpringMongoGeospatialOperations.java:32:      DefaultMongoImperativeExecutor executor, MongoManifestRegistry manifests) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoCollectionManifest.java:93:     * <p>Duplicates are accepted here and rejected by {@link MongoManifestRegistry}: a builder that
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoManifestRegistry.java:21:public final class MongoManifestRegistry {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoManifestRegistry.java:25:  private MongoManifestRegistry(Map<String, MongoCollectionManifest> byCollection) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoManifestRegistry.java:30:  public static MongoManifestRegistry of(MongoCollectionManifest... manifests) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoManifestRegistry.java:35:  public static MongoManifestRegistry of(Collection<MongoCollectionManifest> manifests) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoManifestRegistry.java:48:    return new MongoManifestRegistry(Map.copyOf(byCollection));
exit=0

=== 8.2 recordApplied: the interface contract vs the two implementations ===
$ grep -n 'only if the fence is still the current one' -A 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLedger.java
19:   * Records a completed migration, only if the fence is still the current one.
20-   *
21-   * <p>Conditioned on the fence because the runner that wrote the batches may no longer be the
22-   * runner that owns the lease. A ledger entry from a superseded runner says a migration completed
23-   * when the work it describes was overwritten by the runner that replaced it.
24-   *
25-   * @param fence the acquisition token from {@link MongoMigrationLock#fence()}
26-   * @throws dev.caskeleton.adapter.outbound.mongo.api.error.MongoOperationRejectedException when a
27-   *     newer acquisition exists
--
40:   * Stores a checkpoint after a completed batch, only if the fence is still the current one.
41-   *
42-   * @param fence the acquisition token from {@link MongoMigrationLock#fence()}
43-   * @throws dev.caskeleton.adapter.outbound.mongo.api.error.MongoOperationRejectedException when a
44-   *     newer acquisition exists
45-   */
46-  void saveCheckpoint(MongoMigrationCheckpoint checkpoint, long fence);
47-
48-  /** One applied migration. */
exit=0

$ grep -n 'public void recordApplied' -A 22 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLedger.java
83:  public void recordApplied(
84-      MongoMigrationId migrationId,
85-      MongoMigrationChecksum checksum,
86-      String operator,
87-      Instant appliedAt,
88-      long fence) {
89-    Objects.requireNonNull(migrationId, "migrationId");
90-    Objects.requireNonNull(checksum, "checksum");
91-    Objects.requireNonNull(operator, "operator");
92-    Objects.requireNonNull(appliedAt, "appliedAt");
93-    requireCurrentFence(fence, "ledger entry for " + migrationId.value());
94-    ledger.insertOne(
95-        new Document(MIGRATION_ID, migrationId.value())
96-            .append("checksum", checksum.value())
97-            .append("operator", operator)
98-            .append("appliedAt", Date.from(appliedAt))
99-            .append("fence", fence));
100-  }
101-
102-  @Override
103-  public Optional<MongoMigrationCheckpoint> findCheckpoint(MongoMigrationId migrationId) {
104-    Objects.requireNonNull(migrationId, "migrationId");
105-    Document found = checkpoints.find(Filters.eq(MIGRATION_ID, migrationId.value())).first();
exit=0

$ grep -n 'public void recordApplied' -A 12 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockLedgerAdapter.java
56:  public void recordApplied(
57-      MongoMigrationId migrationId,
58-      MongoMigrationChecksum checksum,
59-      String operator,
60-      Instant appliedAt,
61-      long fence) {
62-    recorded.put(
63-        Objects.requireNonNull(migrationId, "migrationId"),
64-        new AppliedMigration(migrationId, checksum, operator, appliedAt));
65-  }
66-
67-  @Override
68-  public Optional<MongoMigrationCheckpoint> findCheckpoint(MongoMigrationId migrationId) {
exit=0

$ grep -n 'requireCurrentFence' -A 12 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLedger.java
93:    requireCurrentFence(fence, "ledger entry for " + migrationId.value());
94-    ledger.insertOne(
95-        new Document(MIGRATION_ID, migrationId.value())
96-            .append("checksum", checksum.value())
97-            .append("operator", operator)
98-            .append("appliedAt", Date.from(appliedAt))
99-            .append("fence", fence));
100-  }
101-
102-  @Override
103-  public Optional<MongoMigrationCheckpoint> findCheckpoint(MongoMigrationId migrationId) {
104-    Objects.requireNonNull(migrationId, "migrationId");
105-    Document found = checkpoints.find(Filters.eq(MIGRATION_ID, migrationId.value())).first();
--
120:    requireCurrentFence(fence, "checkpoint for " + checkpoint.migrationId().value());
121-    // Conditioned on the stored fence as well as matched by id: a superseded runner that wakes up
122-    // mid-batch must not move the checkpoint of the runner that replaced it, which would send the
123-    // live migration back over rows it has already done or forward past rows it has not.
124-    Document document =
125-        new Document(MIGRATION_ID, checkpoint.migrationId().value())
126-            .append("resumePosition", checkpoint.resumePosition())
127-            .append("processedCount", checkpoint.processedCount())
128-            .append("updatedAt", Date.from(checkpoint.updatedAt()))
129-            .append("fence", fence);
130-
131-    // Replace-then-insert rather than one upsert, and the two cases this separates are the whole
132-    // behaviour of the fence.
--
177:  private static void requireCurrentFence(long fence, String what) {
178-    if (fence == MongoMigrationLock.UNFENCED) {
179-      throw MongoOperationRejectedException.of(
180-          "migration.fence",
181-          "refusing to write the "
182-              + what
183-              + " under an unfenced lease; a lease with no acquisition token cannot show that this"
184-              + " runner is still the one migrating");
185-    }
186-  }
187-}
exit=0

=== 8.2b the diff's comparable field set vs what the manifest declares ===
$ grep -n 'public record MongoIndexManifest' -A 16 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoIndexManifest.java
21:public record MongoIndexManifest(
22-    String name,
23-    List<MongoIndexKey> keys,
24-    boolean unique,
25-    boolean sparse,
26-    boolean hidden,
27-    boolean deprecated,
28-    String partialFilterExpression,
29-    String collationProfile,
30-    Duration expireAfter,
31-    String wildcardProjection,
32-    boolean shardKeySupport,
33-    Set<String> expectedUsage,
34-    String owner,
35-    MongoMetadataOwnership metadataOwnership) {
36-
37-  public MongoIndexManifest {
exit=0

$ grep -n 'public record MongoIndexDescriptorView' -A 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDescriptorView.java
14:public record MongoIndexDescriptorView(
15-    String collection,
16-    String name,
17-    String keySignature,
18-    boolean unique,
19-    boolean hidden,
20-    MongoMetadataOwnership metadataOwnership) {
21-
22-  /** MongoDB's own index on {@code _id}. */
exit=0

$ grep -n 'keySignature().equals\|unique() !=\|expireAfter\|sparse\|partialFilter\|collation\|wildcard' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngine.java
49:      if (!actual.keySignature().equals(declared.keySignature())
50:          || actual.unique() != declared.unique()) {
exit=0

=== 8.2c the diff has no case for an index hidden on the server but declared visible ===
$ grep -n 'hidden' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/index/MongoIndexDiffEngine.java
55:      if (declared.hidden() && !actual.hidden()) {
exit=0

=== 8.3 TTL declared two ways: manifest expireAfter vs MongoTtlPolicy ===
$ grep -n 'expireAfter' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoIndexManifest.java
30:    Duration expireAfter,
54:    if (expireAfter != null && expireAfter.isNegative()) {
73:    return Optional.ofNullable(expireAfter);
78:    return expireAfter != null;
114:    private Duration expireAfter;
189:    public Builder expireAfter(Duration retention) {
190:      this.expireAfter = Objects.requireNonNull(retention, "retention");
235:          expireAfter,
exit=0

$ git grep -n 'MongoTtlPolicyValidator\|MongoTtlIndexDescriptor\|MongoTtlPolicy\b' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/schema/ttl/'
exit=1

$ git grep -n 'isTtlIndex\|\.ttl()' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/manifest/MongoIndexManifest.java:77:  public boolean isTtlIndex() {
exit=0

$ git grep -n 'MINIMUM_SAFE_RETENTION' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoTtlPolicyValidator.java:21:  public static final Duration MINIMUM_SAFE_RETENTION = Duration.ofMinutes(1);
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoTtlPolicyValidator.java:49:    if (!policy.retention().isZero() && policy.retention().compareTo(MINIMUM_SAFE_RETENTION) < 0) {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/schema/ttl/MongoTtlPolicyValidator.java:55:              + MINIMUM_SAFE_RETENTION
exit=0

=== 8.3b two ledgers, two locks, and what the unfenced adapter can actually run ===
$ git grep -n 'implements MongoMigrationLedger\|implements MongoMigrationLock' -- 'adapter/outbound/persistence-mongo/src/main'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLedger.java:29:public final class MongoCollectionMigrationLedger implements MongoMigrationLedger {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLock.java:28:public final class MongoCollectionMigrationLock implements MongoMigrationLock {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockLedgerAdapter.java:24:public final class FlamingockLedgerAdapter implements MongoMigrationLedger {
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockLockAdapter.java:17:public final class FlamingockLockAdapter implements MongoMigrationLock {
exit=0

$ grep -n 'refuses resumable migrations under an unfenced lease' -B 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/flamingock/FlamingockLockAdapter.java
40-    return held.get();
41-  }
42-
43-  /**
44-   * Unfenced: the engine's lock exposes no monotonic token.
45-   *
46-   * <p>Reported honestly rather than synthesised from a local counter, which would look like
47-   * fencing and protect nothing — a per-process counter says nothing about what another process
48:   * acquired. The runner refuses resumable migrations under an unfenced lease for exactly this
exit=0

$ grep -n 'UNFENCED' -A 10 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationRunner.java
82:    if (lock.fence() == MongoMigrationLock.UNFENCED) {
83-      // An unfenced lease cannot tell a live runner from a stalled one that is about to wake up.
84-      // Refused rather than downgraded: the alternative is a certification that says "one runner at
85-      // a time" and a mechanism that cannot show it.
86-      throw MongoOperationRejectedException.of(
87-          "migration.fence",
88-          "this migration lease exposes no fencing token, so a stalled runner cannot be excluded;"
89-              + " use a fenced lease or run the migration inside a maintenance window with the"
90-              + " application stopped");
91-    }
92-
exit=0

=== 8.3c ensureIndexes: who calls it ===
$ git grep -n 'ensureIndexes' -- 'adapter/outbound/persistence-mongo/src'
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLedger.java:62:  public void ensureIndexes() {
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java:78:      ledger.ensureIndexes();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java:129:    ledger.ensureIndexes();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java:152:    writer.ensureIndexes();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java:178:    ledger.ensureIndexes();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java:206:    ledger.ensureIndexes();
adapter/outbound/persistence-mongo/src/test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java:225:    ledger.ensureIndexes();
exit=0

=== 8.4 documentation and lane drift ===
$ grep -rn 'mongoMigrationTest\|mongodb-migration' adapter/outbound/persistence-mongo/build.gradle
97:                'mongodb-migration',
119:    lane('mongoMigrationTest') {
120:        tag = 'mongodb-migration'
exit=0

$ grep -rn 'mongodb-migration\|mongoMigrationTest' ../docs ../README.md 2>/dev/null | head -30
../docs/reviews/2026-08-14-mongodb-module-code-review.md:1127:./gradlew :adapter:outbound:persistence-mongo:mongoMigrationTest --no-daemon --console=plain
../docs/superpowers/plans/2026-08-15-wave6-final-qualification.md:88:  :adapter:outbound:persistence-mongo:mongoMigrationTest \
../docs/superpowers/plans/evidence/2026-08-15-wave0-baseline.md:163:registered: [mongoReplicaSetTest, mongoFailoverTest, mongoMigrationTest, mongoCompatibilityTest,
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-b5-ghost-release-lanes.md:57:`mongoStableContractTest`, `mongoReplicaSetTest`, `mongoFailoverTest`, `mongoMigrationTest`,
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-mongo-lanes.log:22:> Task :adapter:outbound:persistence-mongo:mongoMigrationTest
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-mongo-lanes-first-run-failed.log:23:> Task :adapter:outbound:persistence-mongo:mongoMigrationTest
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-mongo-lanes-first-run-failed.log:30:> Task :adapter:outbound:persistence-mongo:mongoMigrationTest FAILED
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-mongo-lanes-first-run-failed.log:35:Execution failed for task ':adapter:outbound:persistence-mongo:mongoMigrationTest'.
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-mongo-lanes-first-run-failed.log:36:> There were failing tests. See the report at: file:///home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/persistence-mongo/build/reports/tests/mongoMigrationTest/index.html
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-mongo-migration.log:1:$ ./gradlew :adapter:outbound:persistence-mongo:mongoMigrationTest --console=plain
../docs/superpowers/plans/evidence/2026-08-15-wave6-final/task2-mongo-migration.log:22:> Task :adapter:outbound:persistence-mongo:mongoMigrationTest
../docs/superpowers/plans/2026-08-15-wave2-module-on-path.md:594:        :adapter:outbound:persistence-mongo:mongoMigrationTest \
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:58:│   ├── mongodb-migration-core/
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:59:│   ├── mongodb-migration-flamingock/
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:109:mongodb-migration-core
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:113:mongodb-migration-flamingock
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:114:  → mongodb-migration-core
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:139:- Create: `modules/mongodb/mongodb-migration-core/build.gradle.kts`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:140:- Create: `modules/mongodb/mongodb-migration-flamingock/build.gradle.kts`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:195:        "mongodb-geospatial", "mongodb-migration-core",
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:196:        "mongodb-migration-flamingock", "mongodb-observability",
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:221:git add 'build-logic/src/main/kotlin/mongodb-library-conventions.gradle.kts' 'modules/mongodb/mongodb-core-api/build.gradle.kts' 'modules/mongodb/mongodb-spring-data/build.gradle.kts' 'modules/mongodb/mongodb-imperative/build.gradle.kts' 'modules/mongodb/mongodb-reactive/build.gradle.kts' 'modules/mongodb/mongodb-query/build.gradle.kts' 'modules/mongodb/mongodb-aggregation/build.gradle.kts' 'modules/mongodb/mongodb-transaction/build.gradle.kts' 'modules/mongodb/mongodb-index-schema/build.gradle.kts' 'modules/mongodb/mongodb-change-stream/build.gradle.kts' 'modules/mongodb/mongodb-geospatial/build.gradle.kts' 'modules/mongodb/mongodb-migration-core/build.gradle.kts' 'modules/mongodb/mongodb-migration-flamingock/build.gradle.kts' 'modules/mongodb/mongodb-observability/build.gradle.kts' 'modules/mongodb/mongodb-security/build.gradle.kts' 'modules/mongodb/mongodb-spring-boot-starter/build.gradle.kts' 'modules/mongodb/mongodb-testkit-core/build.gradle.kts' 'modules/mongodb/mongodb-testkit-replicaset/build.gradle.kts' 'modules/mongodb/mongodb-testkit-failover/build.gradle.kts' 'modules/mongodb/mongodb-testkit-migration/build.gradle.kts' 'settings.gradle.kts' 'build-logic/src/test/java/MongoDbModuleBoundaryTest.java'
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1755:- Create: `modules/mongodb/mongodb-migration-core/src/main/java/io/backend/skeleton/mongodb/migration/MongoMigration.java`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1756:- Create: `modules/mongodb/mongodb-migration-core/src/main/java/io/backend/skeleton/mongodb/migration/MongoMigrationId.java`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1757:- Create: `modules/mongodb/mongodb-migration-core/src/main/java/io/backend/skeleton/mongodb/migration/MongoMigrationChecksum.java`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1758:- Create: `modules/mongodb/mongodb-migration-core/src/main/java/io/backend/skeleton/mongodb/migration/MongoMigrationLedger.java`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1759:- Create: `modules/mongodb/mongodb-migration-core/src/main/java/io/backend/skeleton/mongodb/migration/MongoMigrationCheckpoint.java`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1760:- Create: `modules/mongodb/mongodb-migration-core/src/main/java/io/backend/skeleton/mongodb/migration/MongoMigrationRunner.java`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1761:- Test: `modules/mongodb/mongodb-migration-core/src/test/java/io/backend/skeleton/mongodb/migration/MongoMigrationRunnerTest.java`
../docs/superpowers/plans/2026-08-11-mongodb-document-persistence-platform-implementation-plan.md:1794:./gradlew :modules:mongodb:mongodb-migration-core:test --tests 'io.backend.skeleton.mongodb.migration.MongoMigrationRunnerTest'
exit=0

$ git grep -n 'schema.manifest\|MongoManifestRegistry\|MongoMigrationRunner' -- 'adapter/outbound/persistence-mongo/README.md' 2>/dev/null
exit=1

$ ls adapter/outbound/persistence-mongo/src/main/resources 2>/dev/null; find adapter/outbound/persistence-mongo/src -name '*.json' -path '*schema*' | head
META-INF
exit=0

