456 lines
20 KiB
JSON
456 lines
20 KiB
JSON
{
|
||
"schema_version": "backup_dr_target_inventory_v1",
|
||
"generated_at": "2026-06-04T15:38:22+08:00",
|
||
"source_refs": [
|
||
"docs/runbooks/BACKUP-STATUS.md",
|
||
"docs/runbooks/OFFSITE-BACKUP-ESCROW-RUNBOOK.md",
|
||
"scripts/backup/backup-all.sh",
|
||
"scripts/backup/backup-status.sh",
|
||
"scripts/backup/sync-offsite-backups.sh",
|
||
"scripts/backup/verify-offsite-full-sync.sh",
|
||
"scripts/backup/offsite-escrow-evidence-report.sh",
|
||
"scripts/backup/mark-credential-escrow-verified.sh"
|
||
],
|
||
"program_status": {
|
||
"overall_completion_percent": 88,
|
||
"current_priority": "P1",
|
||
"current_task_id": "P1-101",
|
||
"next_task_id": "P1-102",
|
||
"read_only_mode": true
|
||
},
|
||
"target_taxonomy": {
|
||
"target_types": [
|
||
"database",
|
||
"repository",
|
||
"registry",
|
||
"volume",
|
||
"configuration",
|
||
"route_evidence",
|
||
"ai_artifact",
|
||
"offsite_mirror",
|
||
"credential_escrow",
|
||
"k8s_resource",
|
||
"status_check"
|
||
],
|
||
"statuses": ["active", "partial", "blocked", "deferred"],
|
||
"gate_statuses": [
|
||
"read_only_allowed",
|
||
"backup_execution_blocked",
|
||
"restore_approval_required",
|
||
"offsite_sync_blocked",
|
||
"credential_approval_required",
|
||
"blocked_by_live_evidence",
|
||
"deferred_until_service_active"
|
||
],
|
||
"storage_classes": [
|
||
"restic_local",
|
||
"restic_offsite",
|
||
"file_export",
|
||
"velero_minio",
|
||
"evidence_marker",
|
||
"read_only_metric"
|
||
]
|
||
},
|
||
"rollups": {
|
||
"total_targets": 17,
|
||
"by_status": {
|
||
"active": 14,
|
||
"blocked": 2,
|
||
"deferred": 1
|
||
},
|
||
"by_target_type": {
|
||
"database": 5,
|
||
"repository": 1,
|
||
"registry": 1,
|
||
"volume": 4,
|
||
"configuration": 1,
|
||
"route_evidence": 1,
|
||
"ai_artifact": 1,
|
||
"offsite_mirror": 1,
|
||
"credential_escrow": 1,
|
||
"k8s_resource": 1
|
||
},
|
||
"by_gate_status": {
|
||
"backup_execution_blocked": 13,
|
||
"offsite_sync_blocked": 1,
|
||
"credential_approval_required": 1,
|
||
"blocked_by_live_evidence": 1,
|
||
"deferred_until_service_active": 1
|
||
},
|
||
"blocked_target_ids": [
|
||
"configs_capture",
|
||
"credential_escrow_markers"
|
||
]
|
||
},
|
||
"backup_targets": [
|
||
{
|
||
"target_id": "gitea",
|
||
"display_name": "Gitea DB + repository dump",
|
||
"target_type": "repository",
|
||
"status": "active",
|
||
"risk_level": "critical",
|
||
"owner_host": "110",
|
||
"primary_script": "scripts/backup/backup-gitea.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/gitea",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像到 rclone remote;子腳本不直接 rclone sync。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "不輸出 Gitea app.ini secret;restore 前需人工批准。",
|
||
"evidence_refs": ["scripts/backup/backup-gitea.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 讀取 freshness / integrity 指標,不直接觸發備份。"
|
||
},
|
||
{
|
||
"target_id": "momo_postgresql",
|
||
"display_name": "MOMO PostgreSQL",
|
||
"target_type": "database",
|
||
"status": "active",
|
||
"risk_level": "high",
|
||
"owner_host": "110 pulls from 188",
|
||
"primary_script": "scripts/backup/backup-momo.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/momo",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "PostgreSQL credential 保留在 188 momo-db container env;快照不得記錄 secret 值。",
|
||
"evidence_refs": ["scripts/backup/backup-momo.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 對齊 freshness 與 last failure 指標。"
|
||
},
|
||
{
|
||
"target_id": "harbor",
|
||
"display_name": "Harbor registry + DB",
|
||
"target_type": "registry",
|
||
"status": "active",
|
||
"risk_level": "critical",
|
||
"owner_host": "110",
|
||
"primary_script": "scripts/backup/backup-harbor.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/harbor",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "harbor.yml 只進 encrypted restic;不在 API 顯示內容。",
|
||
"evidence_refs": ["scripts/backup/backup-harbor.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 補 registry freshness / integrity surface。"
|
||
},
|
||
{
|
||
"target_id": "awoooi_postgresql_daily",
|
||
"display_name": "AWOOOI PostgreSQL daily full",
|
||
"target_type": "database",
|
||
"status": "active",
|
||
"risk_level": "critical",
|
||
"owner_host": "110 pulls from 188",
|
||
"primary_script": "scripts/backup/backup-awoooi.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h full backup",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/awoooi",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "舊腳本含 DB credential;新 API 只記 evidence ref,不複製 secret 值。",
|
||
"evidence_refs": ["scripts/backup/backup-awoooi.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 對齊 awoooi_prod / awoooi_dev / k3s_datastore freshness。"
|
||
},
|
||
{
|
||
"target_id": "awoooi_postgresql_frequent",
|
||
"display_name": "AWOOOI PostgreSQL frequent core",
|
||
"target_type": "database",
|
||
"status": "active",
|
||
"risk_level": "critical",
|
||
"owner_host": "110 pulls from 188",
|
||
"primary_script": "scripts/backup/backup-awoooi-frequent.sh",
|
||
"schedule": "08:00 / 14:00 / 20:00 或每 6 小時 cron",
|
||
"rpo": "6h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/awoooi",
|
||
"offsite_policy": "由 offsite sync 按 repo 鏡像,不由高頻腳本直接上傳。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "舊腳本含 DB credential;不得把 secret 寫入治理快照或 API。",
|
||
"evidence_refs": ["scripts/backup/backup-awoooi-frequent.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 6h RPO freshness。"
|
||
},
|
||
{
|
||
"target_id": "langfuse",
|
||
"display_name": "Langfuse AI trace DB",
|
||
"target_type": "database",
|
||
"status": "active",
|
||
"risk_level": "high",
|
||
"owner_host": "110",
|
||
"primary_script": "scripts/backup/backup-langfuse.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/langfuse",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "DB dump 只進 encrypted restic;API 不顯示 dump 內容。",
|
||
"evidence_refs": ["scripts/backup/backup-langfuse.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 AI trace backup freshness。"
|
||
},
|
||
{
|
||
"target_id": "monitoring",
|
||
"display_name": "Prometheus / Grafana / Alertmanager",
|
||
"target_type": "volume",
|
||
"status": "active",
|
||
"risk_level": "high",
|
||
"owner_host": "110",
|
||
"primary_script": "scripts/backup/backup-monitoring.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/monitoring",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "Grafana / Alertmanager 設定只進 encrypted restic;不輸出 secret。",
|
||
"evidence_refs": ["scripts/backup/backup-monitoring.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 對齊 monitoring repo freshness 與 alert rules visibility。"
|
||
},
|
||
{
|
||
"target_id": "signoz",
|
||
"display_name": "SignOz ClickHouse + SQLite",
|
||
"target_type": "volume",
|
||
"status": "active",
|
||
"risk_level": "high",
|
||
"owner_host": "110",
|
||
"primary_script": "scripts/backup/backup-signoz.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/signoz",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "腳本會短暫停 collector;Agent 不得任意觸發。",
|
||
"evidence_refs": ["scripts/backup/backup-signoz.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 標出 service-disruptive backup 腳本,避免自動觸發。"
|
||
},
|
||
{
|
||
"target_id": "open_webui",
|
||
"display_name": "Open-WebUI volume",
|
||
"target_type": "volume",
|
||
"status": "active",
|
||
"risk_level": "medium",
|
||
"owner_host": "110 pulls from 188",
|
||
"primary_script": "scripts/backup/backup-open-webui.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/open-webui",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "volume 內容只進 encrypted restic。",
|
||
"evidence_refs": ["scripts/backup/backup-open-webui.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 freshness 與 188 SSH reachability。"
|
||
},
|
||
{
|
||
"target_id": "clawbot_redis",
|
||
"display_name": "ClawBot Redis volume",
|
||
"target_type": "volume",
|
||
"status": "active",
|
||
"risk_level": "medium",
|
||
"owner_host": "110 pulls from 188",
|
||
"primary_script": "scripts/backup/backup-clawbot.sh",
|
||
"schedule": "每日 02:00 via backup-all.sh",
|
||
"rpo": "24h",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/clawbot",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "BGSAVE / volume export 不顯示 Redis payload。",
|
||
"evidence_refs": ["scripts/backup/backup-clawbot.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 freshness 與 failure-only notification。"
|
||
},
|
||
{
|
||
"target_id": "configs_capture",
|
||
"display_name": "Host / service / K8s configuration capture",
|
||
"target_type": "configuration",
|
||
"status": "blocked",
|
||
"risk_level": "critical",
|
||
"owner_host": "110 with SSH to 188 / 120 / 121 / 125",
|
||
"primary_script": "scripts/backup/backup-configs.sh",
|
||
"schedule": "納入 offsite expected repos;live status 顯示 120 target blocked",
|
||
"rpo": "24h target but currently blocked by live evidence",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/configs",
|
||
"offsite_policy": "rclone expected repo includes configs;config capture failure blocks full DR green。",
|
||
"automation_gate_status": "blocked_by_live_evidence",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "Secret / ConfigMap 只進 encrypted restic;不得在 API 顯示內容。",
|
||
"evidence_refs": ["scripts/backup/backup-configs.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 `120-k3s-host-configs` blocked status;不得自動重跑 restore。"
|
||
},
|
||
{
|
||
"target_id": "ai_artifacts",
|
||
"display_name": "AI artifacts / Ollama manifests",
|
||
"target_type": "ai_artifact",
|
||
"status": "active",
|
||
"risk_level": "medium",
|
||
"owner_host": "110 pulls from 188",
|
||
"primary_script": "scripts/backup/backup-ai-artifacts.sh",
|
||
"schedule": "repo expected by offsite sync",
|
||
"rpo": "24h evidence target",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/ai-artifacts",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "預設備份 manifests / Modelfile,不備份 large blobs;不輸出 secret。",
|
||
"evidence_refs": ["scripts/backup/backup-ai-artifacts.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 manifest-only policy 與 freshness。"
|
||
},
|
||
{
|
||
"target_id": "public_routes",
|
||
"display_name": "Public routes / DNS / TLS evidence",
|
||
"target_type": "route_evidence",
|
||
"status": "active",
|
||
"risk_level": "high",
|
||
"owner_host": "110 with public read-only probes",
|
||
"primary_script": "scripts/backup/backup-public-routes.sh",
|
||
"schedule": "repo expected by offsite sync",
|
||
"rpo": "24h evidence target",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/public-routes",
|
||
"offsite_policy": "sync-offsite-backups.sh 統一鏡像。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "不輸出 registrar / DNS provider token;TLS private keys 由 encrypted configs 備份處理。",
|
||
"evidence_refs": ["scripts/backup/backup-public-routes.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 DNS / TLS evidence freshness。"
|
||
},
|
||
{
|
||
"target_id": "sentry",
|
||
"display_name": "Sentry backup repo",
|
||
"target_type": "volume",
|
||
"status": "deferred",
|
||
"risk_level": "medium",
|
||
"owner_host": "110",
|
||
"primary_script": "scripts/backup/backup-sentry.sh",
|
||
"schedule": "deferred until service is active",
|
||
"rpo": "not active",
|
||
"storage_class": "restic_local",
|
||
"storage_ref": "/backup/sentry",
|
||
"offsite_policy": "included in offsite expected repos when local repo exists。",
|
||
"automation_gate_status": "deferred_until_service_active",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "Sentry volume / env 不在 API 顯示。",
|
||
"evidence_refs": ["scripts/backup/backup-sentry.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "服務重新啟動後再評估 freshness;目前不宣稱 active。"
|
||
},
|
||
{
|
||
"target_id": "offsite_rclone_full_sync",
|
||
"display_name": "Google Drive / rclone offsite mirror",
|
||
"target_type": "offsite_mirror",
|
||
"status": "active",
|
||
"risk_level": "critical",
|
||
"owner_host": "110",
|
||
"primary_script": "scripts/backup/sync-offsite-backups.sh",
|
||
"schedule": "每日 03:00 sync;每日 07:20 verify",
|
||
"rpo": "24h mirror target",
|
||
"storage_class": "restic_offsite",
|
||
"storage_ref": "gdrive:awoooi-backups/restic",
|
||
"offsite_policy": "latest-only remote mirror;full sync 需 enable marker 與 resource preflight。",
|
||
"automation_gate_status": "offsite_sync_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "不讀、不輸出 rclone token 或 provider credential。",
|
||
"evidence_refs": ["scripts/backup/sync-offsite-backups.sh", "scripts/backup/verify-offsite-full-sync.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 offsite marker freshness 與 remote latest-only verify。"
|
||
},
|
||
{
|
||
"target_id": "credential_escrow_markers",
|
||
"display_name": "Credential escrow evidence markers",
|
||
"target_type": "credential_escrow",
|
||
"status": "blocked",
|
||
"risk_level": "critical",
|
||
"owner_host": "110 + external human vault",
|
||
"primary_script": "scripts/backup/mark-credential-escrow-verified.sh",
|
||
"schedule": "人工審查後寫非 secret marker",
|
||
"rpo": "manual review cadence",
|
||
"storage_class": "evidence_marker",
|
||
"storage_ref": "/backup/escrow-evidence/*.last_verified",
|
||
"offsite_policy": "marker 只記非 secret evidence id;credential 本體不進 repo / API。",
|
||
"automation_gate_status": "credential_approval_required",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "禁止 secret、URL、token、password 寫入 marker;只接受短 evidence id。",
|
||
"evidence_refs": ["scripts/backup/mark-credential-escrow-verified.sh", "scripts/backup/offsite-escrow-evidence-report.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-105 起草人工 escrow review 批准包;目前 5/5 marker missing。"
|
||
},
|
||
{
|
||
"target_id": "velero_k8s_resources",
|
||
"display_name": "Velero K8s resource snapshots",
|
||
"target_type": "k8s_resource",
|
||
"status": "active",
|
||
"risk_level": "critical",
|
||
"owner_host": "188 K8s / MinIO",
|
||
"primary_script": "k8s/awoooi-prod/16-cronjob-backup-restore-test.yaml",
|
||
"schedule": "每日 02:00 Velero / restore test path",
|
||
"rpo": "24h",
|
||
"storage_class": "velero_minio",
|
||
"storage_ref": "MinIO bucket: velero",
|
||
"offsite_policy": "MinIO 是備份的備份;仍需獨立 offsite 評估。",
|
||
"automation_gate_status": "backup_execution_blocked",
|
||
"restore_gate_status": "restore_approval_required",
|
||
"secret_policy": "K8s Secret restore / readback 需人工批准;API 不顯示 Secret payload。",
|
||
"evidence_refs": ["docs/runbooks/BACKUP-STATUS.md", "k8s/awoooi-prod/16-cronjob-backup-restore-test.yaml"],
|
||
"next_action": "P1-102 顯示 Velero freshness;P1-105 才處理 restore drill 批准包。"
|
||
}
|
||
],
|
||
"readiness_surfaces": [
|
||
{
|
||
"surface_id": "backup_status_daily_summary",
|
||
"display_name": "每日備份心跳摘要",
|
||
"script_or_metric": "scripts/backup/backup-status.sh",
|
||
"mode": "read_only",
|
||
"status": "active",
|
||
"evidence_refs": ["scripts/backup/backup-status.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 將 freshness / integrity / restore drill 指標轉成準備度矩陣。"
|
||
},
|
||
{
|
||
"surface_id": "offsite_full_verify",
|
||
"display_name": "Offsite latest-only 驗證",
|
||
"script_or_metric": "scripts/backup/verify-offsite-full-sync.sh --write-textfile",
|
||
"mode": "read_only",
|
||
"status": "active",
|
||
"evidence_refs": ["scripts/backup/verify-offsite-full-sync.sh", "docs/runbooks/BACKUP-STATUS.md"],
|
||
"next_action": "P1-102 顯示 remote snapshots=1 與 verifier freshness。"
|
||
},
|
||
{
|
||
"surface_id": "escrow_evidence_report",
|
||
"display_name": "Offsite / credential escrow evidence report",
|
||
"script_or_metric": "scripts/backup/offsite-escrow-evidence-report.sh",
|
||
"mode": "read_only",
|
||
"status": "blocked",
|
||
"evidence_refs": ["scripts/backup/offsite-escrow-evidence-report.sh", "scripts/backup/mark-credential-escrow-verified.sh"],
|
||
"next_action": "P1-105 產出人工 escrow review 批准包;不得自動寫 marker。"
|
||
}
|
||
],
|
||
"operation_boundaries": {
|
||
"read_only_api_allowed": true,
|
||
"backup_execution_allowed": false,
|
||
"restore_execution_allowed": false,
|
||
"offsite_sync_execution_allowed": false,
|
||
"credential_marker_write_allowed": false,
|
||
"schedule_change_allowed": false,
|
||
"destructive_prune_allowed": false
|
||
},
|
||
"approval_boundaries": {
|
||
"sdk_installation_allowed": false,
|
||
"paid_api_call_allowed": false,
|
||
"shadow_or_canary_allowed": false,
|
||
"production_routing_allowed": false,
|
||
"destructive_operation_allowed": false
|
||
}
|
||
}
|