# MongoDB Advanced Capabilities Expansion Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Stable MongoDB 문서 영속성 플랫폼의 공개 계약을 변경하지 않고 Sharding, Time Series, CSFLE, Queryable Encryption, Search, Vector Search, Multi-tenancy, Change Stream Messaging Bridge와 GridFS migration compatibility를 선택 모듈로 구현한다. **Architecture:** 모든 기능은 `modules/mongodb-advanced`에 격리되고 명시적 feature flag, 별도 privilege, 별도 topology 또는 provider gate를 요구한다. Stable Starter는 이 모듈을 자동 의존하지 않는다. Application-plane descriptor/guardrail과 Admin-plane topology/index/key 변경을 분리한다. **Tech Stack:** Stable MongoDB platform, Java 21, Spring Boot 4.1 BOM, Spring Data MongoDB 5.1, MongoDB 8.0 primary lane, actual Sharded Cluster, Atlas Local, actual target Atlas/KMS environments, existing Messaging and Object Storage platforms. ## Global Constraints - Stable Task 1~50과 Stable Release Gate가 먼저 통과해야 한다. - Advanced module root는 `modules/mongodb-advanced`이다. - 모든 기능은 `backend.mongodb.advanced..enabled=true`를 요구한다. - Advanced 모듈은 Stable Starter의 transitive dependency가 아니다. - Sharding, Search, Encryption, Migration과 Tenant administration은 별도 credential을 사용한다. - Time Series는 일반 Collection capability를 상속하지 않는다. - CSFLE와 Queryable Encryption을 같은 Collection에 동시에 적용하지 않는다. - MongoDB 8.0 Stable에서 QE prefix/suffix/substring query를 지원하지 않는다. - Search/Vector index creation과 READY 상태를 분리한다. - Shared Collection tenancy는 tenant context 누락 시 fail-closed다. - Database-per-tenant는 client/migration concurrency를 제한한다. - Change Stream 원본을 Messaging 외부 계약으로 직접 발행하지 않는다. - GridFS는 legacy read/migration compatibility 전용이다. - 승격에는 실제 topology/provider, security, failure, migration, performance와 runbook evidence가 필요하다. --- ### Task 1: Advanced 모듈·Feature Flag·Dependency 격리 구성 **Files:** - Create: `build-logic/src/main/kotlin/mongodb-advanced-library-conventions.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-sharding/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-timeseries/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-csfle/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-queryable-encryption/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-search/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-vector-search/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-tenancy-shared/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-tenancy-database/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-gridfs-compat/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-testkit-sharded/build.gradle.kts` - Create: `modules/mongodb-advanced/mongodb-testkit-atlas/build.gradle.kts` - Modify: `settings.gradle.kts` - Test: `build-logic/src/test/java/MongoDbAdvancedModuleBoundaryTest.java` **Interfaces:** - Consumes: Completed Stable Tasks 1~50 and Stable release evidence. - Produces: 12 opt-in modules under `modules/mongodb-advanced` with explicit feature flags and no Stable Starter dependency. **Implementation requirements:** - Require Stable Release Gate evidence before advanced test suites run. - Every capability requires `backend.mongodb.advanced..enabled=true`. - No advanced module may be a transitive dependency of mongodb-spring-boot-starter. - Admin privileges and actual target-environment tests are capability-specific. - Promotion to Stable requires a separate ADR and evidence package. - [ ] **Step 1: Write the failing test** ```java class MongoDbAdvancedModuleBoundaryTest { @org.junit.jupiter.api.Test void stableStarterHasNoAdvancedDependency() { org.assertj.core.api.Assertions.assertThat( MongoAdvancedBuildModel.dependenciesOf("mongodb-spring-boot-starter")) .noneMatch(it -> it.startsWith("mongodb-advanced")); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew build-logic:test --tests 'MongoDbAdvancedModuleBoundaryTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public final class MongoAdvancedBuildModel { public static boolean enabled(String capability, java.util.Map flags) { return Boolean.TRUE.equals(flags.get(capability)); } } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew build-logic:test --tests 'MongoDbAdvancedModuleBoundaryTest' ./gradlew :modules:mongodb-advanced:mongodb-sharding:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'build-logic/src/main/kotlin/mongodb-advanced-library-conventions.gradle.kts' 'modules/mongodb-advanced/mongodb-sharding/build.gradle.kts' 'modules/mongodb-advanced/mongodb-timeseries/build.gradle.kts' 'modules/mongodb-advanced/mongodb-csfle/build.gradle.kts' 'modules/mongodb-advanced/mongodb-queryable-encryption/build.gradle.kts' 'modules/mongodb-advanced/mongodb-search/build.gradle.kts' 'modules/mongodb-advanced/mongodb-vector-search/build.gradle.kts' 'modules/mongodb-advanced/mongodb-tenancy-shared/build.gradle.kts' 'modules/mongodb-advanced/mongodb-tenancy-database/build.gradle.kts' 'modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/build.gradle.kts' 'modules/mongodb-advanced/mongodb-gridfs-compat/build.gradle.kts' 'modules/mongodb-advanced/mongodb-testkit-sharded/build.gradle.kts' 'modules/mongodb-advanced/mongodb-testkit-atlas/build.gradle.kts' 'settings.gradle.kts' 'build-logic/src/test/java/MongoDbAdvancedModuleBoundaryTest.java' git commit -m "build: add isolated mongodb advanced modules" ``` ### Task 2: Shard Key Descriptor와 Targeted Query Validator 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardKeyDescriptor.java` - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardKeyPart.java` - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardStrategy.java` - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardAwareQueryValidator.java` - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/MongoRoutingClassification.java` - Test: `modules/mongodb-advanced/mongodb-sharding/src/test/java/io/backend/skeleton/mongodb/advanced/sharding/ShardAwareQueryValidatorTest.java` **Interfaces:** - Consumes: Stable collection/query/index manifests and operation contexts. - Produces: Application-plane classification of targeted, prefix-targeted and scatter-gather queries. **Implementation requirements:** - Descriptor must preserve compound shard-key order and hashed/range strategy. - Single-document writes must include routing evidence required by the server version and collection profile. - Unique indexes must be checked for shard-key compatibility. - Scatter-gather operations require an explicit reviewed profile and telemetry. - Do not execute shardCollection, refine or reshard through this module. - [ ] **Step 1: Write the failing test** ```java class ShardAwareQueryValidatorTest { @org.junit.jupiter.api.Test void classifiesMissingShardKeyAsScatterGather() { ShardKeyDescriptor key = ShardKeyDescriptor.range("tenantId", "orderId"); MongoRoutingClassification result = new ShardAwareQueryValidator().classify(key, java.util.Set.of("status")); org.assertj.core.api.Assertions.assertThat(result) .isEqualTo(MongoRoutingClassification.SCATTER_GATHER); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-sharding:test --tests 'io.backend.skeleton.mongodb.advanced.sharding.ShardAwareQueryValidatorTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public enum MongoRoutingClassification { TARGETED, PREFIX_TARGETED, SCATTER_GATHER, REJECTED } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-sharding:test --tests 'io.backend.skeleton.mongodb.advanced.sharding.ShardAwareQueryValidatorTest' ./gradlew :modules:mongodb-advanced:mongodb-sharding:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardKeyDescriptor.java' 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardKeyPart.java' 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardStrategy.java' 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/ShardAwareQueryValidator.java' 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/MongoRoutingClassification.java' 'modules/mongodb-advanced/mongodb-sharding/src/test/java/io/backend/skeleton/mongodb/advanced/sharding/ShardAwareQueryValidatorTest.java' git commit -m "feat: add mongodb shard aware query validation" ``` ### Task 3: analyzeShardKey Readiness Report와 D4 Sharding Admin 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ShardKeyReadinessReport.java` - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ShardKeyAnalyzer.java` - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/MongoShardingAdminGateway.java` - Create: `modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ReshardApproval.java` - Test: `modules/mongodb-advanced/mongodb-sharding/src/test/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ShardKeyAnalyzerTest.java` **Interfaces:** - Consumes: Shard descriptors, D4 admin security and actual server sampling. - Produces: Cardinality, frequency, monotonicity, read/write distribution and reshard readiness evidence. **Implementation requirements:** - Run analyzeShardKey only through a shard-admin credential. - Report cardinality, frequency, monotonicity, skew and sampled routing distribution. - Require supporting index and query-manifest coverage before shardCollection approval. - Refine and reshard require dry-run, operator reason, rollback/forward strategy and audit. - Balancer, zones and shard add/remove remain explicit Admin operations. - [ ] **Step 1: Write the failing test** ```java class ShardKeyAnalyzerTest { @org.junit.jupiter.api.Test void rejectsLowCardinalityCandidate() { ShardKeyReadinessReport report = ShardKeyReadinessReport.lowCardinality("status"); org.assertj.core.api.Assertions.assertThat(report.approved()).isFalse(); org.assertj.core.api.Assertions.assertThat(report.reasons()) .contains("LOW_CARDINALITY"); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-sharding:test --tests 'io.backend.skeleton.mongodb.advanced.sharding.admin.ShardKeyAnalyzerTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public record ShardKeyReadinessReport( boolean approved, java.util.Set reasons, double monotonicity, double readTargetingRatio, double writeTargetingRatio) { } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-sharding:test --tests 'io.backend.skeleton.mongodb.advanced.sharding.admin.ShardKeyAnalyzerTest' ./gradlew :modules:mongodb-advanced:mongodb-sharding:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ShardKeyReadinessReport.java' 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ShardKeyAnalyzer.java' 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/MongoShardingAdminGateway.java' 'modules/mongodb-advanced/mongodb-sharding/src/main/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ReshardApproval.java' 'modules/mongodb-advanced/mongodb-sharding/src/test/java/io/backend/skeleton/mongodb/advanced/sharding/admin/ShardKeyAnalyzerTest.java' git commit -m "feat: add mongodb shard key readiness and admin gate" ``` ### Task 4: 실제 Sharded Cluster Testkit과 Chunk Migration 계약 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-testkit-sharded/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoShardedCluster.java` - Create: `modules/mongodb-advanced/mongodb-testkit-sharded/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoChunkMigrationController.java` - Create: `modules/mongodb-advanced/mongodb-testkit-sharded/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoShardingContractSuite.java` - Create: `modules/mongodb-advanced/mongodb-testkit-sharded/src/test/resources/mongodb/init-sharded-cluster.js` - Test: `modules/mongodb-advanced/mongodb-testkit-sharded/src/test/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoShardingContractSuiteTest.java` **Interfaces:** - Consumes: Sharding module, Testcontainers/Docker and Stable platform contracts. - Produces: Actual mongos/config-server/shard topology tests for targeting, migration, failover and cross-shard transactions. **Implementation requirements:** - Run at least two shards and a replicated config server for release evidence. - Verify targeted versus scatter-gather execution through explain and telemetry. - Move chunks while reads, writes and change streams are active. - Test shard-key-missing single-document updates and unique-index restrictions. - Test cross-shard transaction failure and recovery without hiding latency cost. - [ ] **Step 1: Write the failing test** ```java class MongoShardingContractSuiteTest { @org.junit.jupiter.api.Test void targetedQueryTouchesOneShard() { MongoShardingReport report = MongoShardingContractSuite.runTargetedQuery(); org.assertj.core.api.Assertions.assertThat(report.shardsExamined()).isEqualTo(1); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-testkit-sharded:test --tests 'io.backend.skeleton.mongodb.advanced.testkit.sharded.MongoShardingContractSuiteTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public interface MongoShardingContractSuite { static MongoShardingReport runTargetedQuery() { return new MongoShardingReport(1, MongoRoutingClassification.TARGETED); } } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-testkit-sharded:test --tests 'io.backend.skeleton.mongodb.advanced.testkit.sharded.MongoShardingContractSuiteTest' ./gradlew :modules:mongodb-advanced:mongodb-testkit-sharded:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-testkit-sharded/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoShardedCluster.java' 'modules/mongodb-advanced/mongodb-testkit-sharded/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoChunkMigrationController.java' 'modules/mongodb-advanced/mongodb-testkit-sharded/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoShardingContractSuite.java' 'modules/mongodb-advanced/mongodb-testkit-sharded/src/test/resources/mongodb/init-sharded-cluster.js' 'modules/mongodb-advanced/mongodb-testkit-sharded/src/test/java/io/backend/skeleton/mongodb/advanced/testkit/sharded/MongoShardingContractSuiteTest.java' git commit -m "test: add mongodb sharded cluster contract suite" ``` ### Task 5: Time Series 전용 Collection·Write·Query 계약 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesDescriptor.java` - Create: `modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesGranularity.java` - Create: `modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesOperations.java` - Create: `modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesCapabilityValidator.java` - Test: `modules/mongodb-advanced/mongodb-timeseries/src/test/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesCapabilityValidatorTest.java` **Interfaces:** - Consumes: Stable manifests, D4 collection setup and MongoDB 8.0 capability reports. - Produces: Separate timeField/metaField/granularity/bucket/TTL API that does not inherit general collection capabilities. **Implementation requirements:** - Reject schema validator, change stream, CSFLE, search and transaction-write combinations. - Require explicit timeField, optional metaField and bounded granularity/bucket settings. - Validate server-version-specific sharding restrictions. - Expose TTL as time-series retention, not an exact scheduler. - Test document-size and update limitations separately from normal collections. - [ ] **Step 1: Write the failing test** ```java class MongoTimeSeriesCapabilityValidatorTest { @org.junit.jupiter.api.Test void rejectsChangeStreamOnTimeSeries() { MongoTimeSeriesDescriptor descriptor = MongoTimeSeriesDescriptor.standard("observedAt", "sensor"); org.assertj.core.api.Assertions.assertThatThrownBy(() -> new MongoTimeSeriesCapabilityValidator().requireChangeStream(descriptor)) .isInstanceOf(UnsupportedOperationException.class); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-timeseries:test --tests 'io.backend.skeleton.mongodb.advanced.timeseries.MongoTimeSeriesCapabilityValidatorTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public record MongoTimeSeriesDescriptor( String timeField, String metaField, MongoTimeSeriesGranularity granularity, java.time.Duration retention) { } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-timeseries:test --tests 'io.backend.skeleton.mongodb.advanced.timeseries.MongoTimeSeriesCapabilityValidatorTest' ./gradlew :modules:mongodb-advanced:mongodb-timeseries:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesDescriptor.java' 'modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesGranularity.java' 'modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesOperations.java' 'modules/mongodb-advanced/mongodb-timeseries/src/main/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesCapabilityValidator.java' 'modules/mongodb-advanced/mongodb-timeseries/src/test/java/io/backend/skeleton/mongodb/advanced/timeseries/MongoTimeSeriesCapabilityValidatorTest.java' git commit -m "feat: add mongodb time series capability" ``` ### Task 6: CSFLE Automatic·Explicit Encryption 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleProfile.java` - Create: `modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleFieldPolicy.java` - Create: `modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoDataKeyResolver.java` - Create: `modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleClientFactory.java` - Test: `modules/mongodb-advanced/mongodb-csfle/src/test/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleFieldPolicyTest.java` **Interfaces:** - Consumes: Security profiles, D4 admin client, BSON manifest and actual KMS/key-vault fixtures. - Produces: Randomized/deterministic field encryption with key resolver and no plaintext telemetry. **Implementation requirements:** - Randomized encryption is the default for non-queryable PII. - Deterministic encryption requires a documented equality-query requirement and leakage review. - Key-vault access uses a dedicated principal. - Plaintext fields, KMS material and data keys never enter logs, traces or failure metadata. - CSFLE cannot be enabled on a time-series collection or mixed with QE on the same collection. - [ ] **Step 1: Write the failing test** ```java class MongoCsfleFieldPolicyTest { @org.junit.jupiter.api.Test void nonQueryablePiiDefaultsToRandomizedEncryption() { MongoCsfleFieldPolicy policy = MongoCsfleFieldPolicy.forPii("ssn", false); org.assertj.core.api.Assertions.assertThat(policy.mode()) .isEqualTo(MongoCsfleMode.RANDOMIZED); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-csfle:test --tests 'io.backend.skeleton.mongodb.advanced.encryption.csfle.MongoCsfleFieldPolicyTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public record MongoCsfleFieldPolicy( String fieldPath, MongoCsfleMode mode, String keyAlias) { } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-csfle:test --tests 'io.backend.skeleton.mongodb.advanced.encryption.csfle.MongoCsfleFieldPolicyTest' ./gradlew :modules:mongodb-advanced:mongodb-csfle:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleProfile.java' 'modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleFieldPolicy.java' 'modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoDataKeyResolver.java' 'modules/mongodb-advanced/mongodb-csfle/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleClientFactory.java' 'modules/mongodb-advanced/mongodb-csfle/src/test/java/io/backend/skeleton/mongodb/advanced/encryption/csfle/MongoCsfleFieldPolicyTest.java' git commit -m "feat: add mongodb csfle capability" ``` ### Task 7: Queryable Encryption Equality·Range 계약 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoQueryableEncryptionProfile.java` - Create: `modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoEncryptedFieldDescriptor.java` - Create: `modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoQueryableEncryptionCollectionManager.java` - Create: `modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoEncryptionMetadataOwnership.java` - Test: `modules/mongodb-advanced/mongodb-queryable-encryption/src/test/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoQueryableEncryptionProfileTest.java` **Interfaces:** - Consumes: Security, D4 admin, schema/index ownership and KMS test environment. - Produces: QE equality and range profiles with protected internal metadata ownership. **Implementation requirements:** - MongoDB 8.0 Stable supports equality and range only. - Prefix, suffix and substring query profiles are rejected. - Encrypted collection setup is a D4 operation completed before application writes. - Mark `__safeContent__` and internal metadata collections as ENCRYPTION_MANAGED. - Key rotation and compaction/cleanup require separate runbooks and evidence. - [ ] **Step 1: Write the failing test** ```java class MongoQueryableEncryptionProfileTest { @org.junit.jupiter.api.Test void mongoEightRejectsSubstringQueryableEncryption() { org.assertj.core.api.Assertions.assertThatThrownBy(() -> MongoQueryableEncryptionProfile.substring("name")) .isInstanceOf(UnsupportedOperationException.class); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-queryable-encryption:test --tests 'io.backend.skeleton.mongodb.advanced.encryption.qe.MongoQueryableEncryptionProfileTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public enum MongoQueryableEncryptionQueryType { EQUALITY, RANGE } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-queryable-encryption:test --tests 'io.backend.skeleton.mongodb.advanced.encryption.qe.MongoQueryableEncryptionProfileTest' ./gradlew :modules:mongodb-advanced:mongodb-queryable-encryption:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoQueryableEncryptionProfile.java' 'modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoEncryptedFieldDescriptor.java' 'modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoQueryableEncryptionCollectionManager.java' 'modules/mongodb-advanced/mongodb-queryable-encryption/src/main/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoEncryptionMetadataOwnership.java' 'modules/mongodb-advanced/mongodb-queryable-encryption/src/test/java/io/backend/skeleton/mongodb/advanced/encryption/qe/MongoQueryableEncryptionProfileTest.java' git commit -m "feat: add mongodb queryable encryption equality and range" ``` ### Task 8: MongoDB Search Query·Index Readiness 계약 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchIndexDescriptor.java` - Create: `modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchIndexState.java` - Create: `modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchQuery.java` - Create: `modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchOperations.java` - Create: `modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchReadinessGate.java` - Test: `modules/mongodb-advanced/mongodb-search/src/test/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchReadinessGateTest.java` **Interfaces:** - Consumes: Aggregation guardrails, D4 admin and Atlas environment capability. - Produces: Search indexes with CREATED/BUILDING/READY/FAILED states and bounded typed queries. **Implementation requirements:** - Index creation success is not equivalent to READY. - Application search queries run only against an index proven READY. - Search query paths and operators are allowlisted. - Actual target deployment validates analyzers, relevance and latency. - Legacy `$text` remains compatibility-only and is not silently redirected to Search. - [ ] **Step 1: Write the failing test** ```java class MongoSearchReadinessGateTest { @org.junit.jupiter.api.Test void buildingIndexCannotServeTraffic() { MongoSearchReadinessGate gate = new MongoSearchReadinessGate(); org.assertj.core.api.Assertions.assertThatThrownBy(() -> gate.requireReady(MongoSearchIndexState.BUILDING)) .isInstanceOf(MongoOperationRejectedException.class); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-search:test --tests 'io.backend.skeleton.mongodb.advanced.search.MongoSearchReadinessGateTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public enum MongoSearchIndexState { CREATED, BUILDING, READY, FAILED, DELETING } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-search:test --tests 'io.backend.skeleton.mongodb.advanced.search.MongoSearchReadinessGateTest' ./gradlew :modules:mongodb-advanced:mongodb-search:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchIndexDescriptor.java' 'modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchIndexState.java' 'modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchQuery.java' 'modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchOperations.java' 'modules/mongodb-advanced/mongodb-search/src/main/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchReadinessGate.java' 'modules/mongodb-advanced/mongodb-search/src/test/java/io/backend/skeleton/mongodb/advanced/search/MongoSearchReadinessGateTest.java' git commit -m "feat: add mongodb search readiness contract" ``` ### Task 9: Vector Search와 Embedding·Score 계약 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorIndexDescriptor.java` - Create: `modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoEmbedding.java` - Create: `modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorQuery.java` - Create: `modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorSearchOperations.java` - Create: `modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorSearchBenchmarkGate.java` - Test: `modules/mongodb-advanced/mongodb-vector-search/src/test/java/io/backend/skeleton/mongodb/advanced/vector/MongoEmbeddingTest.java` **Interfaces:** - Consumes: Search readiness, operation budgets and Atlas test environment. - Produces: Typed embedding dimension, similarity metric, candidate/result limits and benchmark evidence. **Implementation requirements:** - Embedding dimension must exactly match the registered index. - Similarity metric and score interpretation are part of the index contract. - Bound numCandidates, result count, filter fields and timeout. - Do not return raw provider score without a named score contract. - Actual deployment benchmarks accuracy, latency, memory and index readiness. - [ ] **Step 1: Write the failing test** ```java class MongoEmbeddingTest { @org.junit.jupiter.api.Test void rejectsDimensionMismatch() { MongoVectorIndexDescriptor index = MongoVectorIndexDescriptor.cosine("embedding", 3); org.assertj.core.api.Assertions.assertThatThrownBy(() -> MongoEmbedding.forIndex(index, new float[]{1f, 2f})) .isInstanceOf(IllegalArgumentException.class); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-vector-search:test --tests 'io.backend.skeleton.mongodb.advanced.vector.MongoEmbeddingTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public record MongoEmbedding(float[] values) { public MongoEmbedding { values = values.clone(); } @Override public float[] values() { return values.clone(); } } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-vector-search:test --tests 'io.backend.skeleton.mongodb.advanced.vector.MongoEmbeddingTest' ./gradlew :modules:mongodb-advanced:mongodb-vector-search:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorIndexDescriptor.java' 'modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoEmbedding.java' 'modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorQuery.java' 'modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorSearchOperations.java' 'modules/mongodb-advanced/mongodb-vector-search/src/main/java/io/backend/skeleton/mongodb/advanced/vector/MongoVectorSearchBenchmarkGate.java' 'modules/mongodb-advanced/mongodb-vector-search/src/test/java/io/backend/skeleton/mongodb/advanced/vector/MongoEmbeddingTest.java' git commit -m "feat: add mongodb vector search contract" ``` ### Task 10: Shared Collection Multi-tenancy Guardrail 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantContext.java` - Create: `modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/TenantScopedMongoOperations.java` - Create: `modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantPredicateInjector.java` - Create: `modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantManifestValidator.java` - Test: `modules/mongodb-advanced/mongodb-tenancy-shared/src/test/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantPredicateInjectorTest.java` **Interfaces:** - Consumes: Stable query/aggregation/index/change-stream modules and security context. - Produces: Fail-closed tenant predicate injection for find, update, delete, aggregation and change-stream projection. **Implementation requirements:** - Missing tenant context rejects all tenant-scoped operations. - Inject tenant predicate into find/update/delete and require a bounded first-stage match for aggregation. - Validate tenant participation in unique indexes when uniqueness is tenant-scoped. - Do not assume tenantId is always the correct shard key; use shard-key analysis. - Never expose raw tenant IDs in metrics or general logs. - [ ] **Step 1: Write the failing test** ```java class MongoTenantPredicateInjectorTest { @org.junit.jupiter.api.Test void missingTenantContextFailsClosed() { MongoTenantPredicateInjector injector = new MongoTenantPredicateInjector(); org.assertj.core.api.Assertions.assertThatThrownBy(() -> injector.apply(java.util.Optional.empty(), AtomicFilter.id("o-1"))) .isInstanceOf(MongoOperationRejectedException.class); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-tenancy-shared:test --tests 'io.backend.skeleton.mongodb.advanced.tenancy.shared.MongoTenantPredicateInjectorTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public record MongoTenantContext(String opaqueTenantKey) { public MongoTenantContext { if (opaqueTenantKey == null || opaqueTenantKey.isBlank()) { throw new IllegalArgumentException("tenant context required"); } } } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-tenancy-shared:test --tests 'io.backend.skeleton.mongodb.advanced.tenancy.shared.MongoTenantPredicateInjectorTest' ./gradlew :modules:mongodb-advanced:mongodb-tenancy-shared:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantContext.java' 'modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/TenantScopedMongoOperations.java' 'modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantPredicateInjector.java' 'modules/mongodb-advanced/mongodb-tenancy-shared/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantManifestValidator.java' 'modules/mongodb-advanced/mongodb-tenancy-shared/src/test/java/io/backend/skeleton/mongodb/advanced/tenancy/shared/MongoTenantPredicateInjectorTest.java' git commit -m "feat: add shared collection mongodb tenancy guardrails" ``` ### Task 11: Database-per-tenant Routing·Migration·Client Lifecycle 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantDatabaseResolver.java` - Create: `modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantClientRegistry.java` - Create: `modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantMigrationCoordinator.java` - Create: `modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantLifecyclePolicy.java` - Test: `modules/mongodb-advanced/mongodb-tenancy-database/src/test/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantClientRegistryTest.java` **Interfaces:** - Consumes: Stable profile/client generation, migration core and security modules. - Produces: Bounded tenant database routing, client caching, migration fan-out and offboarding lifecycle. **Implementation requirements:** - Tenant-to-database mapping comes from a trusted registry, never request input. - Bound cached clients and close idle generations. - Migration fan-out uses concurrency and rate limits with per-tenant checkpoints. - A tenant database cannot become active before schema/index validation succeeds. - Offboarding requires retention, export and delete evidence. - [ ] **Step 1: Write the failing test** ```java class MongoTenantClientRegistryTest { @org.junit.jupiter.api.Test void registryEnforcesMaximumActiveClients() { MongoTenantClientRegistry registry = new MongoTenantClientRegistry(2); registry.acquire("t1"); registry.acquire("t2"); org.assertj.core.api.Assertions.assertThatThrownBy(() -> registry.acquire("t3")) .isInstanceOf(MongoOperationRejectedException.class); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-tenancy-database:test --tests 'io.backend.skeleton.mongodb.advanced.tenancy.database.MongoTenantClientRegistryTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public interface MongoTenantDatabaseResolver { DatabaseProfileName resolve(MongoTenantContext tenant); } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-tenancy-database:test --tests 'io.backend.skeleton.mongodb.advanced.tenancy.database.MongoTenantClientRegistryTest' ./gradlew :modules:mongodb-advanced:mongodb-tenancy-database:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantDatabaseResolver.java' 'modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantClientRegistry.java' 'modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantMigrationCoordinator.java' 'modules/mongodb-advanced/mongodb-tenancy-database/src/main/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantLifecyclePolicy.java' 'modules/mongodb-advanced/mongodb-tenancy-database/src/test/java/io/backend/skeleton/mongodb/advanced/tenancy/database/MongoTenantClientRegistryTest.java' git commit -m "feat: add database per tenant mongodb lifecycle" ``` ### Task 12: Change Stream → Messaging 안정 Bridge 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoChangeToIntegrationEventMapper.java` - Create: `modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoChangeMessagingBridge.java` - Create: `modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoBridgeOutboxPolicy.java` - Create: `modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoBridgeCheckpointPolicy.java` - Test: `modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/test/java/io/backend/skeleton/mongodb/advanced/bridge/MongoChangeMessagingBridgeTest.java` **Interfaces:** - Consumes: Stable Change Stream projector and the existing Messaging Platform typed publisher. - Produces: Mapping of physical changes to versioned integration events with idempotent publish/checkpoint semantics. **Implementation requirements:** - Never publish raw MongoDB change events as external contracts. - Integration event type, schema version and message ID are mapper-owned stable values. - Publish and checkpoint ambiguity must preserve duplicate-safe message identity. - Document where Change Stream bridge is insufficient and Transactional Outbox is required. - Messaging failures must not silently advance the MongoDB checkpoint. - [ ] **Step 1: Write the failing test** ```java class MongoChangeMessagingBridgeTest { @org.junit.jupiter.api.Test void failedPublishDoesNotAdvanceMongoCheckpoint() { MongoBridgeProbe probe = MongoBridgeProbe.publishFails(); probe.bridge().handle(probe.change()).block(); org.assertj.core.api.Assertions.assertThat(probe.checkpointWrites()).isZero(); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-change-stream-messaging-bridge:test --tests 'io.backend.skeleton.mongodb.advanced.bridge.MongoChangeMessagingBridgeTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public interface MongoChangeToIntegrationEventMapper { MessagingEnvelope map(MongoChangeEventIdentity identity, org.bson.BsonDocument change); } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-change-stream-messaging-bridge:test --tests 'io.backend.skeleton.mongodb.advanced.bridge.MongoChangeMessagingBridgeTest' ./gradlew :modules:mongodb-advanced:mongodb-change-stream-messaging-bridge:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoChangeToIntegrationEventMapper.java' 'modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoChangeMessagingBridge.java' 'modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoBridgeOutboxPolicy.java' 'modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/main/java/io/backend/skeleton/mongodb/advanced/bridge/MongoBridgeCheckpointPolicy.java' 'modules/mongodb-advanced/mongodb-change-stream-messaging-bridge/src/test/java/io/backend/skeleton/mongodb/advanced/bridge/MongoChangeMessagingBridgeTest.java' git commit -m "feat: add mongodb change stream messaging bridge" ``` ### Task 13: GridFS Legacy Compatibility와 Object Storage Migration Adapter 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsCompatibilityReader.java` - Create: `modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsMigrationJob.java` - Create: `modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsMigrationCheckpoint.java` - Create: `modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsObjectReference.java` - Test: `modules/mongodb-advanced/mongodb-gridfs-compat/src/test/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsMigrationJobTest.java` **Interfaces:** - Consumes: Fileserver/Object Storage ContentStore contract and migration core. - Produces: Read-only legacy GridFS compatibility plus resumable migration to the single file source of truth. **Implementation requirements:** - Do not expose new upload APIs backed by GridFS. - Read GridFS metadata and bytes without creating a second domain file lifecycle. - Migrate bytes to ContentStore, verify size/checksum, then write the new FileId/ContentKey reference. - Checkpoint migration and preserve retry-safe deterministic identities. - Delete legacy GridFS content only through a separate audited cleanup phase. - [ ] **Step 1: Write the failing test** ```java class MongoGridFsMigrationJobTest { @org.junit.jupiter.api.Test void sourceIsRetainedUntilTargetChecksumIsVerified() { MongoGridFsMigrationProbe probe = MongoGridFsMigrationProbe.checksumMismatch(); probe.job().migrate(probe.sourceId()); org.assertj.core.api.Assertions.assertThat(probe.sourceDeleted()).isFalse(); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-gridfs-compat:test --tests 'io.backend.skeleton.mongodb.advanced.gridfs.MongoGridFsMigrationJobTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public interface MongoGridFsCompatibilityReader { GridFsLegacyContent open(String legacyId); } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-gridfs-compat:test --tests 'io.backend.skeleton.mongodb.advanced.gridfs.MongoGridFsMigrationJobTest' ./gradlew :modules:mongodb-advanced:mongodb-gridfs-compat:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsCompatibilityReader.java' 'modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsMigrationJob.java' 'modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsMigrationCheckpoint.java' 'modules/mongodb-advanced/mongodb-gridfs-compat/src/main/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsObjectReference.java' 'modules/mongodb-advanced/mongodb-gridfs-compat/src/test/java/io/backend/skeleton/mongodb/advanced/gridfs/MongoGridFsMigrationJobTest.java' git commit -m "feat: add gridfs compatibility migration adapter" ``` ### Task 14: Atlas Local·실제 Atlas Search·Vector·Encryption Testkit 구현 **Files:** - Create: `modules/mongodb-advanced/mongodb-testkit-atlas/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoAtlasLocalContainer.java` - Create: `modules/mongodb-advanced/mongodb-testkit-atlas/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoAtlasCapabilityContractSuite.java` - Create: `modules/mongodb-advanced/mongodb-testkit-atlas/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoActualAtlasReleaseGate.java` - Create: `modules/mongodb-advanced/mongodb-testkit-atlas/src/test/resources/atlas/search-index.json` - Create: `modules/mongodb-advanced/mongodb-testkit-atlas/src/test/resources/atlas/vector-index.json` - Test: `modules/mongodb-advanced/mongodb-testkit-atlas/src/test/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoAtlasCapabilityContractSuiteTest.java` **Interfaces:** - Consumes: Search, vector, CSFLE/QE modules and Testcontainers Atlas Local. - Produces: Fast local contracts plus credentialed actual-target release gates for readiness, query, KMS and rotation. **Implementation requirements:** - Atlas Local is PR/nightly evidence, not the sole production compatibility proof. - Actual target tests are opt-in secret-backed release jobs. - Wait for Search/Vector index READY before queries. - Test wrong KMS key, key-vault permission and credential rotation without plaintext diagnostics. - Persist only bounded capability reports and never provider credentials. - [ ] **Step 1: Write the failing test** ```java class MongoAtlasCapabilityContractSuiteTest { @org.junit.jupiter.api.Test void vectorQueriesWaitForReadyIndex() { MongoAtlasCapabilityReport report = MongoAtlasCapabilityContractSuite.vectorReadiness(); org.assertj.core.api.Assertions.assertThat(report.queriedBeforeReady()).isFalse(); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-testkit-atlas:test --tests 'io.backend.skeleton.mongodb.advanced.testkit.atlas.MongoAtlasCapabilityContractSuiteTest' ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public interface MongoAtlasCapabilityContractSuite { static MongoAtlasCapabilityReport vectorReadiness() { return new MongoAtlasCapabilityReport(false, true); } } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash ./gradlew :modules:mongodb-advanced:mongodb-testkit-atlas:test --tests 'io.backend.skeleton.mongodb.advanced.testkit.atlas.MongoAtlasCapabilityContractSuiteTest' ./gradlew :modules:mongodb-advanced:mongodb-testkit-atlas:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'modules/mongodb-advanced/mongodb-testkit-atlas/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoAtlasLocalContainer.java' 'modules/mongodb-advanced/mongodb-testkit-atlas/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoAtlasCapabilityContractSuite.java' 'modules/mongodb-advanced/mongodb-testkit-atlas/src/main/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoActualAtlasReleaseGate.java' 'modules/mongodb-advanced/mongodb-testkit-atlas/src/test/resources/atlas/search-index.json' 'modules/mongodb-advanced/mongodb-testkit-atlas/src/test/resources/atlas/vector-index.json' 'modules/mongodb-advanced/mongodb-testkit-atlas/src/test/java/io/backend/skeleton/mongodb/advanced/testkit/atlas/MongoAtlasCapabilityContractSuiteTest.java' git commit -m "test: add atlas local and actual target capability gates" ``` ### Task 15: Advanced Capability 문서·승격 ADR·최종 Promotion Gate **Files:** - Create: `docs/mongodb/advanced/sharding.md` - Create: `docs/mongodb/advanced/time-series.md` - Create: `docs/mongodb/advanced/encryption.md` - Create: `docs/mongodb/advanced/search-vector.md` - Create: `docs/mongodb/advanced/multi-tenancy.md` - Create: `docs/mongodb/advanced/gridfs-migration.md` - Create: `docs/adr/ADR-MONGO-ADV-001-capability-promotion.md` - Create: `scripts/verify-mongodb-advanced.sh` - Test: `modules/mongodb-advanced/mongodb-sharding/src/test/java/io/backend/skeleton/mongodb/advanced/MongoAdvancedPromotionGateTest.java` **Interfaces:** - Consumes: Every previous Advanced task and Stable release evidence. - Produces: Capability-specific support matrix, runbooks, promotion ADR and reproducible advanced verification command. **Implementation requirements:** - Each capability documents topology, server version, privilege, unsupported combinations and failure recovery. - Promotion requires actual topology/environment evidence, security review and migration/runbook coverage. - A capability promoted to Stable still remains an opt-in module unless a later starter ADR changes the dependency boundary. - Search/Vector promotion requires relevance and performance evidence, not only functional success. - Database-per-tenant and reshard orchestration remain Experimental until operational scale evidence exists. - [ ] **Step 1: Write the failing test** ```java class MongoAdvancedPromotionGateTest { @org.junit.jupiter.api.Test void everyPromotionRequiresActualEnvironmentEvidence() { MongoAdvancedPromotionEvidence evidence = MongoAdvancedPromotionEvidence.fixture(); org.assertj.core.api.Assertions.assertThat(evidence.requiredCategories()) .contains("actual-topology", "security", "migration", "failure", "runbook"); } } ``` - [ ] **Step 2: Run the focused test and verify the failure** Run: ```bash bash scripts/verify-mongodb-advanced.sh ``` Expected: FAIL because the advanced capability or its gate is not implemented yet. - [ ] **Step 3: Implement the smallest complete production contract** ```java public final class MongoAdvancedPromotionGate { public void verify(MongoAdvancedPromotionEvidence evidence) { evidence.require("stable-platform"); evidence.require("actual-topology"); evidence.require("security"); evidence.require("failure"); evidence.require("runbook"); } } ``` Implement every invariant listed under **Implementation requirements**. The snippet fixes public names and the central safety contract. - [ ] **Step 4: Run the focused test and module suite** Run: ```bash bash scripts/verify-mongodb-advanced.sh ./gradlew :modules:mongodb-advanced:mongodb-sharding:test ``` Expected: PASS with the focused assertion and module suite green. - [ ] **Step 5: Commit the independently reviewable change** ```bash git add 'docs/mongodb/advanced/sharding.md' 'docs/mongodb/advanced/time-series.md' 'docs/mongodb/advanced/encryption.md' 'docs/mongodb/advanced/search-vector.md' 'docs/mongodb/advanced/multi-tenancy.md' 'docs/mongodb/advanced/gridfs-migration.md' 'docs/adr/ADR-MONGO-ADV-001-capability-promotion.md' 'scripts/verify-mongodb-advanced.sh' 'modules/mongodb-advanced/mongodb-sharding/src/test/java/io/backend/skeleton/mongodb/advanced/MongoAdvancedPromotionGateTest.java' git commit -m "docs: add mongodb advanced promotion gate" ```