1140 lines
59 KiB
Markdown
1140 lines
59 KiB
Markdown
# 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.<capability>.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.<capability>.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<String,Boolean> 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<String> 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"
|
|
```
|