feat(mongodb): implement the MongoDB document persistence platform
Implements the mongodb-superpowers-package design: Stable Tasks 1-50 and Advanced Tasks 1-15. The design assumes 19 Stable + 12 Advanced Gradle projects under modules/mongodb*. This repository's fail-closed registry declares exactly 19 leaf identities, so those modules become package boundaries inside the registered leaf :adapter:outbound:persistence-mongo, with the design's module dependency table enforced by ten ArchUnit rules. The mapping and every deviation are recorded in docs/mongodb/repository-adaptation.md. Contract highlights, all enforced by tests rather than convention: - Transaction body retry and commit retry are separate loops. A new session per body attempt; commit-only retry on an unknown commit. The body is never replayed after a commit ambiguity, so a failover cannot become a duplicate. - MongoExecutionOutcome keeps both ambiguous outcomes distinct from success and failure, and MongoFailureContext records only the design-permitted fields. - Failure classification reads server error labels before numeric codes. - BSON representations come from a pinned manifest, never a library default, and a golden type-signature gate fails on any drift. - Index and validator changes go through the manifest and the admin plane; metadata ownership gates every drop. - Every Advanced capability refuses construction unless its flag is enabled. Verified against real servers, not only unit tests. Running the lanes for the first time exposed four defects that a green `check` had hidden: - Four release lanes passed while executing zero tests; the gate now counts executed tests per lane and fails on zero. - The "single replica set" fixture was a standalone, because Testcontainers 2.x needs withReplicaSet(); its test only asserted a connection string. - The three-node fixture was three independent clusters, so no election could occur, and awaitNewPrimary() compared against the post-stop primary. - The migration lease checked modifiedCount, so a same-millisecond refresh read as a lost lease. scripts/verify-mongodb-platform.sh now reports: 9 lanes, 0 skipped, 0 failed, every evidence category produced. scripts/verify-mongodb-advanced.sh reports NOT PROMOTABLE: actual-topology evidence (real sharded cluster, real KMS, real target deployment) is unobtainable here, so it is named rather than assumed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3b5aee50e3
commit
d57d2f62a0
Executable
+141
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# The MongoDB Advanced capability gate (advanced plan Task 15).
|
||||
#
|
||||
# Advanced capabilities are opt-in modules. This script verifies the contracts that can be verified
|
||||
# without provider infrastructure, and then reports -- explicitly -- which promotion evidence it
|
||||
# could NOT produce.
|
||||
#
|
||||
# Required promotion categories (MongoAdvancedPromotionEvidence.REQUIRED):
|
||||
#
|
||||
# stable-platform, actual-topology, security, migration, failure, runbook
|
||||
#
|
||||
# `actual-topology` is the one that cannot be substituted. A container gives a functional pass for
|
||||
# sharding, search, vector and encryption while exercising none of the behaviour that makes them
|
||||
# Advanced rather than Stable: real shard distribution, a real analyzer, a real KMS. Atlas Local is
|
||||
# a pull-request convenience and is not release evidence -- see
|
||||
# MongoAtlasCapabilityContractSuite.Environment.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/verify-mongodb-advanced.sh
|
||||
# MONGODB_DOCKER=1 bash scripts/verify-mongodb-advanced.sh
|
||||
# MONGODB_SHARDED_URI=... MONGODB_ATLAS_URI=... MONGODB_KMS=... bash scripts/verify-mongodb-advanced.sh
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
GRADLE_DIR="${REPO_ROOT}/src"
|
||||
MODULE=':adapter:outbound:persistence-mongo'
|
||||
GRADLE=(./gradlew --console=plain)
|
||||
|
||||
FAILED=()
|
||||
MISSING_EVIDENCE=()
|
||||
|
||||
echo "MongoDB Advanced capability gate"
|
||||
echo "repository: ${REPO_ROOT}"
|
||||
|
||||
# --- stable-platform -------------------------------------------------------------------------
|
||||
# An Advanced capability cannot be promoted over a Stable platform that does not itself pass.
|
||||
echo ""
|
||||
echo "=== [stable-platform] Stable gate"
|
||||
if bash "${REPO_ROOT}/scripts/verify-mongodb-platform.sh"; then
|
||||
echo "stable-platform: supplied"
|
||||
else
|
||||
status=$?
|
||||
if (( status == 2 )); then
|
||||
echo "stable-platform: INCOMPLETE (the Stable gate skipped lanes)"
|
||||
MISSING_EVIDENCE+=("stable-platform (Stable gate incomplete)")
|
||||
else
|
||||
FAILED+=("stable-platform")
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- failure + runbook (hermetic) -------------------------------------------------------------
|
||||
# Every Advanced refusal contract: disabled capability refuses construction, CSFLE/QE cannot share a
|
||||
# collection, QE substring/prefix/suffix unsupported on 8.0, a non-READY search index cannot serve,
|
||||
# undeclared scatter-gather is rejected, a dimension mismatch is refused.
|
||||
echo ""
|
||||
echo "=== [failure] Advanced contract tests"
|
||||
if (cd "${GRADLE_DIR}" && "${GRADLE[@]}" "${MODULE}:test" --tests '*advanced*'); then
|
||||
echo "failure: supplied"
|
||||
else
|
||||
FAILED+=("failure")
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== [runbook] capability documentation"
|
||||
for doc in sharding time-series encryption search-vector multi-tenancy gridfs-migration; do
|
||||
path="${REPO_ROOT}/docs/mongodb/advanced/${doc}.md"
|
||||
if [[ -f "${path}" ]]; then
|
||||
echo " + ${doc}.md"
|
||||
else
|
||||
echo " - ${doc}.md MISSING"
|
||||
FAILED+=("runbook:${doc}")
|
||||
fi
|
||||
done
|
||||
if [[ ! -f "${REPO_ROOT}/docs/adr/ADR-MONGO-ADV-001-capability-promotion.md" ]]; then
|
||||
echo " - ADR-MONGO-ADV-001 MISSING"
|
||||
FAILED+=("runbook:ADR-MONGO-ADV-001")
|
||||
fi
|
||||
|
||||
# --- actual-topology -------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "=== [actual-topology] provider environments"
|
||||
if [[ -n "${MONGODB_SHARDED_URI:-}" ]]; then
|
||||
if (cd "${GRADLE_DIR}" && "${GRADLE[@]}" "${MODULE}:test" --tests '*Shard*' \
|
||||
-Dmongodb.sharded.uri="${MONGODB_SHARDED_URI}"); then
|
||||
echo "actual-topology(sharded): supplied"
|
||||
else
|
||||
FAILED+=("actual-topology:sharded")
|
||||
fi
|
||||
else
|
||||
echo "actual-topology(sharded): no MONGODB_SHARDED_URI"
|
||||
MISSING_EVIDENCE+=("actual-topology: sharded cluster")
|
||||
fi
|
||||
|
||||
if [[ -n "${MONGODB_ATLAS_URI:-}" ]]; then
|
||||
echo "actual-topology(search/vector): MONGODB_ATLAS_URI present"
|
||||
else
|
||||
echo "actual-topology(search/vector): no MONGODB_ATLAS_URI"
|
||||
MISSING_EVIDENCE+=("actual-topology: search/vector on the actual target deployment")
|
||||
fi
|
||||
|
||||
if [[ -n "${MONGODB_KMS:-}" ]]; then
|
||||
echo "actual-topology(encryption): MONGODB_KMS present"
|
||||
else
|
||||
echo "actual-topology(encryption): no MONGODB_KMS"
|
||||
MISSING_EVIDENCE+=("actual-topology: real KMS and key vault")
|
||||
fi
|
||||
|
||||
# --- security + migration ---------------------------------------------------------------------
|
||||
# These are review artefacts, not test runs: a role review and a documented migration path per
|
||||
# capability. The gate records that they are outstanding rather than pretending a green test covers
|
||||
# them.
|
||||
MISSING_EVIDENCE+=("security: per-capability privilege review sign-off")
|
||||
MISSING_EVIDENCE+=("migration: per-capability migration path sign-off")
|
||||
|
||||
# --- Report ------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "---------------------------------------------------------------"
|
||||
if (( ${#FAILED[@]} > 0 )); then
|
||||
echo "ADVANCED GATE: FAILED"
|
||||
for entry in "${FAILED[@]}"; do echo " - ${entry}"; done
|
||||
echo "---------------------------------------------------------------"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "verifiable contracts: PASSED"
|
||||
if (( ${#MISSING_EVIDENCE[@]} > 0 )); then
|
||||
echo ""
|
||||
echo "ADVANCED GATE: NOT PROMOTABLE -- missing evidence:"
|
||||
for entry in "${MISSING_EVIDENCE[@]}"; do echo " ~ ${entry}"; done
|
||||
echo ""
|
||||
echo "A capability stays opt-in until every category in"
|
||||
echo "MongoAdvancedPromotionEvidence.REQUIRED is supplied. See"
|
||||
echo "docs/adr/ADR-MONGO-ADV-001-capability-promotion.md."
|
||||
echo "---------------------------------------------------------------"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "ADVANCED GATE: PASSED"
|
||||
echo "---------------------------------------------------------------"
|
||||
Executable
+158
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# The MongoDB Stable release gate (design §30, plan Task 50).
|
||||
#
|
||||
# Runs every lane that produces one of the Stable evidence categories:
|
||||
#
|
||||
# mapping, transaction, migration, change-stream, security,
|
||||
# failover, performance, compatibility
|
||||
#
|
||||
# The gate exists because "the test suite is green" and "every category has evidence" are different
|
||||
# statements. A suite passes happily with a whole lane skipped -- no Docker, a disabled tag, a
|
||||
# renamed task -- and a release built on that suite has no failover or compatibility evidence at
|
||||
# all, silently. Each lane below is therefore run by name, and a skipped lane is reported as skipped
|
||||
# rather than counted as passed.
|
||||
#
|
||||
# Advanced capabilities are NOT promoted or transitively included here. See
|
||||
# scripts/verify-mongodb-advanced.sh.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/verify-mongodb-platform.sh # hermetic lanes only
|
||||
# MONGODB_DOCKER=1 bash scripts/verify-mongodb-platform.sh # + container lanes
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
GRADLE_DIR="${REPO_ROOT}/src"
|
||||
MODULE=':adapter:outbound:persistence-mongo'
|
||||
GRADLE=(./gradlew --console=plain)
|
||||
|
||||
RESULTS_DIR="${GRADLE_DIR}/adapter/outbound/persistence-mongo/build/test-results"
|
||||
|
||||
RAN=()
|
||||
SKIPPED=()
|
||||
FAILED=()
|
||||
|
||||
# Counts the tests a lane actually executed, from its JUnit XML.
|
||||
#
|
||||
# A lane whose filter matches nothing passes: Gradle runs the task, discovers no tests, and reports
|
||||
# success. That is the failure mode this whole gate exists to prevent -- an empty lane is not
|
||||
# evidence, it is the absence of evidence wearing a green tick. Any lane that reports zero executed
|
||||
# tests is treated as a failure.
|
||||
executed_tests() {
|
||||
local task="$1"
|
||||
local dir="${RESULTS_DIR}/${task}"
|
||||
[[ -d "${dir}" ]] || { echo 0; return; }
|
||||
local total=0
|
||||
shopt -s nullglob
|
||||
for xml in "${dir}"/*.xml; do
|
||||
local count
|
||||
count=$(sed -n 's/.*<testsuite[^>]* tests="\([0-9]*\)".*/\1/p' "${xml}" | head -1)
|
||||
total=$(( total + ${count:-0} ))
|
||||
done
|
||||
shopt -u nullglob
|
||||
echo "${total}"
|
||||
}
|
||||
|
||||
run_lane() {
|
||||
local category="$1"
|
||||
local task="$2"
|
||||
shift 2
|
||||
echo ""
|
||||
echo "=== [${category}] ${task}"
|
||||
if ! (cd "${GRADLE_DIR}" && "${GRADLE[@]}" "${MODULE}:${task}" "$@"); then
|
||||
FAILED+=("${category}:${task}")
|
||||
return
|
||||
fi
|
||||
# `check` aggregates several tasks and has no results directory of its own.
|
||||
if [[ "${task}" == "check" ]]; then
|
||||
RAN+=("${category}:${task}")
|
||||
return
|
||||
fi
|
||||
local executed
|
||||
executed=$(executed_tests "${task}")
|
||||
if (( executed == 0 )); then
|
||||
echo "!!! ${task} passed without executing a single test — the lane's filter matches nothing,"
|
||||
echo "!!! so the '${category}' evidence category is empty."
|
||||
FAILED+=("${category}:${task} (0 tests executed)")
|
||||
else
|
||||
RAN+=("${category}:${task} (${executed} tests)")
|
||||
fi
|
||||
}
|
||||
|
||||
skip_lane() {
|
||||
local category="$1"
|
||||
local task="$2"
|
||||
local reason="$3"
|
||||
echo ""
|
||||
echo "=== [${category}] ${task} -- SKIPPED (${reason})"
|
||||
SKIPPED+=("${category}:${task} (${reason})")
|
||||
}
|
||||
|
||||
docker_available() {
|
||||
[[ "${MONGODB_DOCKER:-0}" == "1" ]] && command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1
|
||||
}
|
||||
|
||||
echo "MongoDB Stable release gate"
|
||||
echo "repository: ${REPO_ROOT}"
|
||||
|
||||
# --- Always-on lanes -------------------------------------------------------------------------
|
||||
# Static analysis, architecture boundaries, unit and hermetic contract tests. These produce the
|
||||
# mapping, transaction, migration, change-stream and security evidence that does not need a server.
|
||||
run_lane "static-analysis" "check" -x "mongoStableContractTest"
|
||||
run_lane "mapping+transaction+migration+change-stream+security" "mongoStableContractTest"
|
||||
|
||||
# --- Container lanes -------------------------------------------------------------------------
|
||||
# A lane that needs Docker inside `check` teaches people to skip `check`, so these are opt-in --
|
||||
# but opting out is recorded, not silent.
|
||||
if docker_available; then
|
||||
run_lane "compatibility" "mongoCompatibilityTest"
|
||||
run_lane "migration" "mongoMigrationTest"
|
||||
run_lane "security" "mongoSecurityIntegrationTest"
|
||||
run_lane "failover" "mongoReplicaSetTest"
|
||||
run_lane "failover" "mongoFailoverTest"
|
||||
run_lane "performance" "mongoPerformanceTest"
|
||||
else
|
||||
reason="MONGODB_DOCKER!=1 or Docker unavailable"
|
||||
skip_lane "compatibility" "mongoCompatibilityTest" "${reason}"
|
||||
skip_lane "migration" "mongoMigrationTest" "${reason}"
|
||||
skip_lane "security" "mongoSecurityIntegrationTest" "${reason}"
|
||||
skip_lane "failover" "mongoReplicaSetTest" "${reason}"
|
||||
skip_lane "failover" "mongoFailoverTest" "${reason}"
|
||||
skip_lane "performance" "mongoPerformanceTest" "${reason}"
|
||||
fi
|
||||
|
||||
# --- Architecture-wide gates -----------------------------------------------------------------
|
||||
echo ""
|
||||
echo "=== [architecture] repository-wide verification"
|
||||
if (cd "${GRADLE_DIR}" \
|
||||
&& "${GRADLE[@]}" verifyCleanArchitectureDependencies \
|
||||
&& "${GRADLE[@]}" :app-bootstrap:test --tests '*CleanArchitectureTest'); then
|
||||
RAN+=("architecture:repository-wide")
|
||||
else
|
||||
FAILED+=("architecture:repository-wide")
|
||||
fi
|
||||
|
||||
# --- Report ------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "---------------------------------------------------------------"
|
||||
echo "ran: ${#RAN[@]}"
|
||||
for entry in "${RAN[@]:-}"; do [[ -n "${entry}" ]] && echo " + ${entry}"; done
|
||||
echo "skipped: ${#SKIPPED[@]}"
|
||||
for entry in "${SKIPPED[@]:-}"; do [[ -n "${entry}" ]] && echo " ~ ${entry}"; done
|
||||
echo "failed: ${#FAILED[@]}"
|
||||
for entry in "${FAILED[@]:-}"; do [[ -n "${entry}" ]] && echo " - ${entry}"; done
|
||||
echo "---------------------------------------------------------------"
|
||||
|
||||
if (( ${#FAILED[@]} > 0 )); then
|
||||
echo "STABLE GATE: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (( ${#SKIPPED[@]} > 0 )); then
|
||||
echo "STABLE GATE: INCOMPLETE -- lanes above were not run, so their evidence categories are absent."
|
||||
echo "A release requires every category. Re-run with MONGODB_DOCKER=1 on a host with Docker."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "STABLE GATE: PASSED -- every evidence category produced."
|
||||
Reference in New Issue
Block a user