#!/usr/bin/env bash set -euo pipefail repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" fail() { echo "ERROR: $*" >&2 exit 1 } source "$repo_root/scripts/backup/lib/common.sh" source "$repo_root/scripts/backup/lib/manifest.sh" source "$repo_root/scripts/backup/lib/report.sh" assert_eq() { local expected="$1" local actual="$2" local message="$3" [[ "$actual" == "$expected" ]] || fail "$message: expected '$expected', got '$actual'" } all_services="$(normalize_service_filter "all")" assert_eq "postgres ory-postgres clickhouse ory-clickhouse config" "$all_services" "all must expand to every supported service" selected_services="$(normalize_service_filter "postgres,config")" assert_eq "postgres config" "$selected_services" "comma-separated services must be normalized in input order" ory_services="$(normalize_service_filter "ory-postgres,ory-clickhouse")" assert_eq "ory-postgres ory-clickhouse" "$ory_services" "ory service filter must not expand to Baron services" if service_enabled "postgres" "$ory_services"; then fail "service_enabled must not match postgres inside ory-postgres" fi if service_enabled "clickhouse" "$ory_services"; then fail "service_enabled must not match clickhouse inside ory-clickhouse" fi service_enabled "ory-postgres" "$ory_services" || fail "service_enabled must match exact ory-postgres token" service_enabled "ory-clickhouse" "$ory_services" || fail "service_enabled must match exact ory-clickhouse token" grep -Fq "drop database if exists" "$repo_root/scripts/backup/lib/clickhouse.sh" \ || fail "ClickHouse restore must drop restored databases before replaying schema/data to avoid duplicate rows or init-table conflicts." grep -Fq "FORMAT RawBLOB" "$repo_root/scripts/backup/lib/clickhouse.sh" \ || fail "ClickHouse dump must store SHOW CREATE TABLE as raw SQL, not escaped TSV." grep -Fq "render_clickhouse_schema" "$repo_root/scripts/backup/lib/clickhouse.sh" \ || fail "ClickHouse restore must route schema files through the compatibility decoder." grep -Fq "s{\\\\n}" "$repo_root/scripts/backup/lib/clickhouse.sh" \ || fail "ClickHouse restore must decode escaped newlines from older schema dumps." grep -Fq "x27" "$repo_root/scripts/backup/lib/clickhouse.sh" \ || fail "ClickHouse restore must decode escaped single quotes from older schema dumps." grep -Fq "filter_clickhouse_stable_row_counts" "$repo_root/scripts/backup/restore.sh" \ || fail "restore verification must not fail on unstable ClickHouse aggregate/view physical row counts." grep -Fq "collect_clickhouse_native_stable_row_counts" "$repo_root/scripts/backup/restore.sh" \ || fail "restore verification must derive ClickHouse expected counts from Native data files." if normalize_service_filter "postgres,unknown" >/tmp/baron-sso-service-filter.out 2>&1; then fail "unknown backup service must be rejected" fi if ! grep -Fq "unknown backup service" /tmp/baron-sso-service-filter.out; then fail "unknown service rejection must explain the service filter problem" fi tmp_dir="$(mktemp -d /tmp/baron-sso-backup-policy.XXXXXX)" trap 'rm -rf "$tmp_dir"' EXIT INT TERM mkdir -p "$tmp_dir/reports" create_manifest "$tmp_dir" "maintenance" "postgres config" manifest="$tmp_dir/manifest.json" [[ -f "$manifest" ]] || fail "create_manifest must write manifest.json" grep -Fq '"format_version": "1"' "$manifest" || fail "manifest must include format_version" grep -Fq '"mode": "maintenance"' "$manifest" || fail "manifest must include backup mode" grep -Fq '"services": [' "$manifest" || fail "manifest must include service list" grep -Fq '"git_commit":' "$manifest" || fail "manifest must include git commit" cat >"$tmp_dir/reports/baron-postgres-row-counts.txt" <<'EOF' public.users:228 public.tenants:266 public.relying_parties:1 EOF cat >"$tmp_dir/reports/ory_hydra-row-counts.txt" <<'EOF' public.hydra_client:5 EOF write_backup_markdown_report "$tmp_dir" "succeeded" "postgres config" '[{"service":"postgres","duration_seconds":2},{"service":"config","duration_seconds":1}]' backup_md="$tmp_dir/reports/backup-report.md" [[ -f "$backup_md" ]] || fail "backup markdown report must be created." grep -Fq "# Baron SSO Backup Report" "$backup_md" || fail "backup report must have a markdown title." grep -Fq "| 사용자 | 228 |" "$backup_md" || fail "backup report must include user count." grep -Fq "| 테넌트 | 266 |" "$backup_md" || fail "backup report must include tenant count." grep -Fq "| RP | 1 |" "$backup_md" || fail "backup report must include RP count." grep -Fq "| postgres | 2 |" "$backup_md" || fail "backup report must include service duration." printf 'original\n' >"$tmp_dir/example.txt" (cd "$tmp_dir" && sha256sum example.txt > checksums.sha256) printf 'changed\n' >"$tmp_dir/example.txt" if BACKUP="$tmp_dir" "$repo_root/scripts/backup/verify-dump.sh" >/tmp/baron-sso-checksum.out 2>&1; then fail "verify-dump must fail on checksum mismatch" fi if ! grep -Fq "checksum verification failed" /tmp/baron-sso-checksum.out; then fail "checksum mismatch output must be explicit" fi if BACKUP="$tmp_dir" CONFIRM_RESTORE="baron-sso" RESTORE_TEST_NON_EMPTY=1 "$repo_root/scripts/backup/restore.sh" --dry-run >/tmp/baron-sso-non-empty-restore.out 2>&1; then fail "restore must reject non-empty targets by default" fi if ! grep -Fq "non-empty restore target is not allowed" /tmp/baron-sso-non-empty-restore.out; then fail "restore must explain the non-empty target guard" fi archive_source="$tmp_dir/archive-source" mkdir -p "$archive_source/reports" create_manifest "$archive_source" "maintenance" "postgres" printf 'archive fixture\n' >"$archive_source/example.txt" (cd "$archive_source" && sha256sum manifest.json example.txt > checksums.sha256) archive_file="$tmp_dir/archive-source.tar.zst" tar --zstd -cf "$archive_file" -C "$tmp_dir" archive-source restore_report="$tmp_dir/restore-report.json" DUMP_FILE="$archive_file" \ CONFIRM_RESTORE="baron-sso" \ RESTORE_REPORT="$restore_report" \ "$repo_root/scripts/backup/restore.sh" --dry-run >/tmp/baron-sso-dump-file-restore.out [[ -f "$restore_report" ]] || fail "restore dry-run with DUMP_FILE must write RESTORE_REPORT." jq -e \ --arg dump_file "$archive_file" \ '.status == "planned" and .dump_file == $dump_file and .backup_dir != null and (.services | index("postgres"))' \ "$restore_report" >/dev/null || fail "restore report must describe planned DUMP_FILE restore." echo "OK: backup scripts enforce parser, manifest, checksum, and restore safety policies"