#!/bin/sh set -eu cd "$(dirname "$0")/.." tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT HUP INT TERM fakebin="$tmp/bin" mkdir "$fakebin" project="thoth-task8" volume_name="${project}_qdrant-data" volume_root="$tmp/volumes" volume_dir="$volume_root/$volume_name" mkdir -p "$volume_dir/collections/demo" printf '%s' before-backup >"$volume_dir/collections/demo/state.json" cat >"$fakebin/docker" <<'SH' #!/bin/sh set -eu log_file=${DOCKER_LOG:?} printf '%s\n' "$*" >>"$log_file" volume_dir_for() { printf '%s/%s\n' "${VOLUME_ROOT:?}" "$1" } run_backup() { volume_name=$1 backup_dir=$2 output_name=$3 staging=$(mktemp -d "${TMPDIR:-/tmp}/fake-qdrant-backup.XXXXXX") mkdir -p "$staging/payload" cat >"$staging/manifest.env" </dev/null test -s "$backup_output" tar -tf "$backup_output" | grep -qx 'manifest.env' tar -tf "$backup_output" | grep -qx 'payload/collections/demo/state.json' tar -xOf "$backup_output" manifest.env | grep -qx 'format=thothii-qdrant-backup-v1' tar -xOf "$backup_output" manifest.env | grep -qx "project_name=$project" tar -xOf "$backup_output" manifest.env | grep -qx "volume_name=$volume_name" grep -q "run --rm --mount type=volume,src=$volume_name,dst=/qdrant-data,readonly --mount type=bind,src=$tmp,dst=/backup" "$docker_log" grep -q "compose --project-name $project stop qdrant" "$docker_log" grep -q "compose --project-name $project start qdrant" "$docker_log" if grep -q "volume inspect --format {{ .Mountpoint }}" "$docker_log"; then echo "backup consulted Docker mountpoints" >&2 exit 1 fi if grep -q "prune" "$docker_log"; then echo "backup attempted global docker cleanup" >&2 exit 1 fi existing="$tmp/existing.tar" printf '%s' sentinel >"$existing" if PATH="$fakebin:$PATH" DOCKER_LOG="$tmp/existing.log" PROJECT_NAME="$project" VOLUME_ROOT="$volume_root" \ HELPER_IMAGE="qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c" \ ./scripts/vector-backup.sh --project-name "$project" --output "$existing" >"$tmp/existing.out" 2>"$tmp/existing.err"; then echo "backup overwrote an existing archive" >&2 exit 1 fi test "$(cat "$existing")" = sentinel if PATH="$fakebin:$PATH" DOCKER_LOG="$tmp/ambiguous.log" PROJECT_NAME="$project" VOLUME_ROOT="$volume_root" \ VOLUME_LS_OUTPUT=multiple HELPER_IMAGE="qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c" \ ./scripts/vector-backup.sh --project-name "$project" --output "$tmp/ambiguous.tar" >"$tmp/ambiguous.out" 2>"$tmp/ambiguous.err"; then echo "backup accepted an ambiguous qdrant-data target" >&2 exit 1 fi grep -q 'exactly one qdrant-data volume' "$tmp/ambiguous.err" foreign_archive="$tmp/foreign.tar" make_foreign_archive "$foreign_archive" printf '%s' before-malicious >"$volume_dir/collections/demo/state.json" foreign_log="$tmp/foreign.log" : >"$foreign_log" if PATH="$fakebin:$PATH" DOCKER_LOG="$foreign_log" PROJECT_NAME="$project" VOLUME_ROOT="$volume_root" \ MOUNTPOINT="/" HELPER_IMAGE="qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c" \ ./scripts/vector-restore.sh --project-name "$project" --input "$foreign_archive" --confirm-project "$project" \ >"$tmp/foreign.out" 2>"$tmp/foreign.err"; then echo "restore accepted a malformed or foreign archive" >&2 exit 1 fi grep -Eq 'manifest|archive|foreign|unexpected|traversal' "$tmp/foreign.err" test "$(cat "$volume_dir/collections/demo/state.json")" = before-malicious if grep -q "compose --project-name $project stop qdrant" "$foreign_log"; then echo "restore stopped qdrant before archive validation" >&2 exit 1 fi if grep -q '^run ' "$foreign_log"; then echo "restore ran helper container before archive validation" >&2 exit 1 fi if grep -q "volume inspect --format {{ .Mountpoint }}" "$foreign_log"; then echo "restore consulted Docker mountpoints during malformed archive rejection" >&2 exit 1 fi symlink_archive="$tmp/symlink.tar" make_symlink_archive "$symlink_archive" symlink_log="$tmp/symlink.log" : >"$symlink_log" if PATH="$fakebin:$PATH" DOCKER_LOG="$symlink_log" PROJECT_NAME="$project" VOLUME_ROOT="$volume_root" \ HELPER_IMAGE="qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c" \ ./scripts/vector-restore.sh --project-name "$project" --input "$symlink_archive" --confirm-project "$project" \ >"$tmp/symlink.out" 2>"$tmp/symlink.err"; then echo "restore accepted a symlink-bearing archive" >&2 exit 1 fi grep -Eq 'symlink|hardlink|device|fifo|socket|archive' "$tmp/symlink.err" if grep -q "compose --project-name $project stop qdrant" "$symlink_log"; then echo "restore stopped qdrant before symlink archive rejection" >&2 exit 1 fi restore_source="$tmp/restore-source" mkdir -p "$restore_source/payload/collections/demo" cat >"$restore_source/manifest.env" <"$restore_source/payload/collections/demo/state.json" restore_input="$tmp/restore.tar" tar -C "$restore_source" -cf "$restore_input" manifest.env payload if PATH="$fakebin:$PATH" DOCKER_LOG="$tmp/confirm.log" PROJECT_NAME="$project" VOLUME_ROOT="$volume_root" \ HELPER_IMAGE="qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c" \ ./scripts/vector-restore.sh --project-name "$project" --input "$restore_input" --confirm-project wrong-project \ >"$tmp/confirm.out" 2>"$tmp/confirm.err"; then echo "restore skipped explicit project confirmation" >&2 exit 1 fi grep -q 'confirmation must match --project-name exactly' "$tmp/confirm.err" printf '%s' modified-live >"$volume_dir/collections/demo/state.json" restore_log="$tmp/restore-ok.log" PATH="$fakebin:$PATH" DOCKER_LOG="$restore_log" PROJECT_NAME="$project" VOLUME_ROOT="$volume_root" \ HELPER_IMAGE="qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c" \ ./scripts/vector-restore.sh --project-name "$project" --input "$restore_input" --confirm-project "$project" >/dev/null test "$(cat "$volume_dir/collections/demo/state.json")" = restored grep -q "compose --project-name $project stop qdrant" "$restore_log" grep -q "compose --project-name $project start qdrant" "$restore_log" grep -q "run --rm --mount type=volume,src=$volume_name,dst=/qdrant-data --mount type=bind,src=$tmp,dst=/restore-backup,readonly" "$restore_log" if grep -q "volume inspect --format {{ .Mountpoint }}" "$restore_log"; then echo "restore consulted Docker mountpoints during normal restore" >&2 exit 1 fi if grep -q "prune" "$restore_log"; then echo "restore attempted global docker cleanup" >&2 exit 1 fi printf '%s' rollback-source >"$volume_dir/collections/demo/state.json" rollback_log="$tmp/restore-rollback.log" if PATH="$fakebin:$PATH" DOCKER_LOG="$rollback_log" PROJECT_NAME="$project" VOLUME_ROOT="$volume_root" \ RUN_FAIL_AFTER_CLEANUP=1 HELPER_IMAGE="qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c" \ ./scripts/vector-restore.sh --project-name "$project" --input "$restore_input" --confirm-project "$project" \ >"$tmp/rollback.out" 2>"$tmp/rollback.err"; then echo "restore ignored helper failure after cleanup" >&2 exit 1 fi test "$(cat "$volume_dir/collections/demo/state.json")" = rollback-source grep -q "compose --project-name $project stop qdrant" "$rollback_log" grep -q "compose --project-name $project start qdrant" "$rollback_log" echo "qdrant backup/restore archive validation, scoped helper execution, and rollback safety passed."