Sub-scope 07 (mongo) schema + migration - execution probes revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5 generatedAt=2026-08-30T00:08:22+00:00 Two temporary probe classes were added, run, and removed: src/test/.../migration/Ss07FenceProbe.java (@Tag mongodb-migration, real server) src/test/.../schema/Ss07SchemaProbe.java (@Tag mongodb-contract, hermetic) No production source was modified. git status after removal is shown at the end. === PROBE A: recordApplied under a stale fence (real MongoDB 8.0 replica set) === Scenario: the live runner holds fence 5 and has stored checkpoint o-900. the superseded runner still holds fence 1. PROBE saveCheckpoint(fence=1 over stored 5) -> REFUSED MongoOperationRejectedException PROBE recordApplied(fence=1 over stored 5) -> ACCEPTED PROBE ledger entry now = Document{{_id=6a937447a11d79601374fd73, migrationId=20260829-001, checksum=superseded, operator=stale-runner, appliedAt=Thu Jan 01 00:00:00 UTC 1970, fence=1}} PROBE live checkpoint still = o-900 PROBE recordApplied(live fence=5, after stale wrote) -> REFUSED MongoWriteException: E11000 duplicate key error collection: ss07probe.mongoMigrationLedger index: migrationId_1 dup key: { migrationId: "20260829-001" } Reading: saveCheckpoint honours the documented fence contract; recordApplied does not. The superseded runner wins the ledger and the live runner receives a raw driver duplicate-key error rather than the platform's lease sentence. This is the same shape the codebase already fixed once inside saveCheckpoint (see its inline comment). === PROBE B: what the index diff cannot see (hermetic) === Declared: ix_ttl (expireAfter=30d), ix_active (sparse, partialFilter, collation, visible) Observed: same names, same keys, same uniqueness; ix_active hidden on the server PROBE diff.isClean() -> true PROBE diff.render() -> [] (empty) PROBE MongoIndexManifest.expireAfter(1s) built -> PT1S isTtlIndex=true Reading: a TTL retention change, a sparse/partialFilter/collation change and an index hidden on the server but declared visible all render as no drift at all. === PROBE C: what the Flamingock lease can run (hermetic) === PROBE FlamingockLockAdapter.fence() = -1 PROBE runner.apply(NON-resumable migration, Flamingock lease) -> REFUSED MongoOperationRejectedException: this migration lease exposes no fencing token, so a stalled runner cannot be excluded; use a fenced lease or run the migration inside a maintenance window with the application stopped [operation=migration.fence ... category=OPERATION_REJECTED outcome=NOT_SENT] Reading: the migration in this probe returns completed(0) and stores no checkpoint, so it is not resumable. FlamingockLockAdapter's javadoc says the runner 'refuses resumable migrations under an unfenced lease'; the runner refuses every migration. === 8.1c is the one production consumer of the manifest registry itself wired? === $ grep -n 'Geospatial\|geo\.' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java exit=1 $ git grep -n 'new SpringMongoGeospatialOperations' -- 'adapter/outbound/persistence-mongo/src/main' exit=1 $ git grep -n 'MongoManifestRegistry\|MongoCollectionManifest' -- 'adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/geo' 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) { exit=0 === 8.1d the migration package's cross-package production consumers === $ git grep -n 'import dev.caskeleton.adapter.outbound.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:3:import dev.caskeleton.adapter.outbound.mongo.migration.MongoMigrationCheckpoint; adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java:6:import dev.caskeleton.adapter.outbound.mongo.migration.MongoMigrationCheckpoint; exit=0 $ grep -n 'MongoMigrationCheckpoint\|MongoMigrationLedger\|MongoMigrationLock\|MongoMigrationRunner' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java 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:6:import dev.caskeleton.adapter.outbound.mongo.migration.MongoMigrationCheckpoint; adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java:73: public void recordCheckpoint(String tenantKey, MongoMigrationCheckpoint checkpoint) { adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java:85: public Optional checkpointFor(String tenantKey) { adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java:98: private final Map byTenant = adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java:105: public Optional find(String tenantKey) { adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCoordinator.java:110: public void save(String tenantKey, MongoMigrationCheckpoint checkpoint) { adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCheckpointStore.java:3:import dev.caskeleton.adapter.outbound.mongo.migration.MongoMigrationCheckpoint; adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCheckpointStore.java:21: Optional find(String tenantKey); adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/advanced/tenancy/database/MongoTenantMigrationCheckpointStore.java:24: void save(String tenantKey, MongoMigrationCheckpoint checkpoint); exit=0 === 8.4b migration lane test count at HEAD === $ ls adapter/outbound/persistence-mongo/build/test-results/mongoMigrationTest/*.xml | head -20 adapter/outbound/persistence-mongo/build/test-results/mongoMigrationTest/TEST-dev.caskeleton.adapter.outbound.mongo.migration.Ss07FenceProbe.xml exit=0 $ grep -ho 'tests="[0-9]*" skipped="[0-9]*" failures="[0-9]*" errors="[0-9]*"' adapter/outbound/persistence-mongo/build/test-results/mongoMigrationTest/*.xml tests="1" skipped="0" failures="0" errors="0" exit=0 === source tree after probe removal === $ git status --short | wc -l 0 exit=0 $ git status --short exit=0 === 8.4b RE-RUN: full mongoMigrationTest lane at HEAD (after probe removal) === $ ./gradlew :adapter:outbound:persistence-mongo:mongoMigrationTest --rerun-tasks > Task :adapter:outbound:persistence-mongo:testClasses > Task :adapter:outbound:persistence-mongo:mongoMigrationTest BUILD SUCCESSFUL in 30s 13 actionable tasks: 13 executed Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.0.0/userguide/configuration_cache_enabling.html classes: 1 tests="8" skipped="0" failures="0" errors="0" git status --short: 0 entries