feat(backup): protect host188 product data

This commit is contained in:
Your Name
2026-07-18 18:39:35 +08:00
parent 592a195676
commit 420738514e
16 changed files with 438 additions and 16 deletions

View File

@@ -15,10 +15,11 @@ EXPECTED_FILES = {
"backup-awoooi-frequent.sh",
"backup-clawbot.sh",
"backup-sentry.sh",
"backup-host188-products.sh",
}
def test_backup_runtime_deploy_is_fixed_to_host_110_and_six_files() -> None:
def test_backup_runtime_deploy_is_fixed_to_host_110_and_seven_files() -> None:
plays = yaml.safe_load(PLAYBOOK.read_text(encoding="utf-8"))
assert len(plays) == 1
play = plays[0]

View File

@@ -22,15 +22,16 @@ REQUIRED_BACKUP_SCRIPTS = (
"backup-ai-artifacts.sh",
"backup-configs.sh",
"backup-public-routes.sh",
"backup-host188-products.sh",
)
def test_backup_all_runs_every_required_domain_once() -> None:
source = BACKUP_ALL.read_text(encoding="utf-8")
assert "local total=13" in source
assert "local total=14" in source
assert [int(value) for value in re.findall(r">>> \[(\d+)/\$\{total\}\]", source)] == list(
range(1, 14)
range(1, 15)
)
for script in REQUIRED_BACKUP_SCRIPTS:
assert source.count(f"/backup/scripts/{script}") == 1

View File

@@ -0,0 +1,101 @@
from __future__ import annotations
from pathlib import Path
ROOT = Path(__file__).resolve().parents[3]
SCRIPT = ROOT / "scripts" / "backup" / "backup-host188-products.sh"
BACKUP_ALL = ROOT / "scripts" / "backup" / "backup-all.sh"
INTEGRITY = ROOT / "scripts" / "backup" / "check-backup-integrity.sh"
OFFSITE_SCRIPTS = (
ROOT / "scripts" / "backup" / "sync-offsite-backups.sh",
ROOT / "scripts" / "backup" / "backup-offsite-readiness-gate.sh",
ROOT / "scripts" / "backup" / "verify-offsite-full-sync.sh",
ROOT / "scripts" / "backup" / "enforce-latest-only-retention.sh",
)
EXPORTER = ROOT / "scripts" / "ops" / "backup-health-textfile-exporter.py"
AGENT99 = ROOT / "agent99-control-plane.ps1"
FULL_PLAYBOOK = ROOT / "infra" / "ansible" / "playbooks" / "110-devops.yml"
BOUNDED_PLAYBOOK = (
ROOT / "infra" / "ansible" / "playbooks" / "110-backup-runtime-deploy.yml"
)
REBOOT_READINESS = (
ROOT
/ "scripts"
/ "reboot-recovery"
/ "reboot-recovery-readiness-audit.sh"
)
def test_host188_product_backup_has_fixed_sources_and_online_verifiers() -> None:
source = SCRIPT.read_text(encoding="utf-8")
for expected in (
'REMOTE_HOST="ollama@192.168.0.188"',
"vibework-production-postgres-1",
"current-fifa2026-postgres-1",
"current-fifa2026-redis-1",
"n8n",
"pg_dump -Fc",
"PGDMP",
"pg_restore --list",
"redis-cli --rdb",
'magic}" != "REDIS"',
"sqlite3.OPEN_READONLY",
"db.backup",
"PRAGMA integrity_check",
"n8n export:workflow --backup",
"n8n export:credentials --backup",
'LOCAL_REPO="${BACKUP_BASE}/host188-products"',
"verify_backup",
):
assert expected in source
def test_host188_product_backup_preserves_secret_and_runtime_boundaries() -> None:
source = SCRIPT.read_text(encoding="utf-8")
assert "umask 077" in source
assert '"credentialsDecrypted": False' in source
assert '"offsiteWritePerformed": False' in source
assert "tarfile.open" in source
assert "n8n_archive_unsafe_path" in source
assert "REDISCLI_AUTH" in source
assert 'if [ "${BACKUP_NOTIFY_SUCCESS:-0}" = "1" ]' in source
assert "handle.read(1024 * 1024)" in source
for forbidden in (
"--decrypted",
"docker stop",
"docker restart",
"docker pause",
"docker compose down",
"docker inspect -f '{{range .Config.Env}}",
"rclone ",
"sync-offsite-backups.sh",
"rm -rf /home/node/.n8n",
"path.read_bytes()",
):
assert forbidden not in source
def test_host188_product_backup_is_wired_into_health_integrity_and_offsite() -> None:
assert "/backup/scripts/backup-host188-products.sh" in BACKUP_ALL.read_text(
encoding="utf-8"
)
assert "host188-products" in INTEGRITY.read_text(encoding="utf-8")
for path in OFFSITE_SCRIPTS:
assert "host188-products" in path.read_text(encoding="utf-8")
exporter = EXPORTER.read_text(encoding="utf-8")
assert '"backup-host188-products.sh"' in exporter
assert '("host188_products", "/backup/host188-products", 48)' in exporter
agent99 = AGENT99.read_text(encoding="utf-8")
assert 'name = "host188-products"' in agent99
assert 'path = "/backup/host188-products/snapshots"' in agent99
assert "maxAgeMinutes = 1800; required = $true" in agent99
for path in (FULL_PLAYBOOK, BOUNDED_PLAYBOOK):
assert "backup-host188-products.sh" in path.read_text(encoding="utf-8")
assert "backup-host188-products.sh" in REBOOT_READINESS.read_text(encoding="utf-8")