{
  "name": "Auto-Backup Verifier",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "20 2 * * *"
            }
          ]
        },
        "timezone": "Australia/Perth"
      },
      "id": "cron-trigger",
      "name": "Daily 02:20 AWST",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [200, 300]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            { "name": "repoOwner", "type": "string", "value": "Anthony" },
            { "name": "repoName", "type": "string", "value": "openclaw-backups" },
            { "name": "branch", "type": "string", "value": "main" },
            { "name": "requiredPaths", "type": "string", "value": "AGENTS.md,MEMORY.md,TOOLS.md,state-backup/openclaw.json,state-backup/cron/jobs.json,state-backup/devices/paired.json" }
          ]
        }
      },
      "id": "set-context",
      "name": "Set Context",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [420, 300]
    },
    {
      "parameters": {
        "url": "=http://gitea.kangaroo-eel.ts.net:3000/api/v1/repos/{{$json.repoOwner}}/{{$json.repoName}}/branches/{{$json.branch}}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": { "timeout": 10000 }
      },
      "id": "get-branch",
      "name": "Get Branch Head",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [660, 300],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    },
    {
      "parameters": {
        "url": "=http://gitea.kangaroo-eel.ts.net:3000/api/v1/repos/{{$node[\"Set Context\"].json.repoOwner}}/{{$node[\"Set Context\"].json.repoName}}/git/trees/{{$json.commit.id}}?recursive=1",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": { "timeout": 10000 }
      },
      "id": "get-tree",
      "name": "Get Repo Tree",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [900, 300],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    },
    {
      "parameters": {
        "jsCode": "const required = $node['Set Context'].json.requiredPaths.split(',').map(s => s.trim());\nconst tree = $json.tree || [];\nconst existing = new Set(tree.map(t => t.path));\nconst missing = required.filter(p => !existing.has(p));\nreturn [{ json: {\n  status: missing.length ? 'failed' : 'ok',\n  missing,\n  checked: required.length,\n  headSha: ($node['Get Branch Head'].json.commit || {}).id || '',\n  repo: `${$node['Set Context'].json.repoOwner}/${$node['Set Context'].json.repoName}`\n}}];"
      },
      "id": "validate",
      "name": "Validate Required Files",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1140, 300]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            { "value1": "={{$json.status}}", "operation": "equals", "value2": "ok" }
          ]
        }
      },
      "id": "if-ok",
      "name": "Backup OK?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [1360, 300]
    },
    {
      "parameters": {
        "url": "=http://runtipi.kangaroo-eel.ts.net:8129/message?token={{$env.GOTIFY_TOKEN}}",
        "sendBody": true,
        "contentType": "json",
        "bodyParameters": {
          "parameters": [
            { "name": "title", "value": "✅ Backup Verified" },
            { "name": "message", "value": "={{`Repo ${$json.repo} verified. SHA: ${$json.headSha.slice(0,7)}. Checked ${$json.checked} required files.`}}" },
            { "name": "priority", "value": "2" }
          ]
        },
        "options": { "timeout": 10000 }
      },
      "id": "notify-ok",
      "name": "Gotify Success",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1600, 200]
    },
    {
      "parameters": {
        "url": "=http://runtipi.kangaroo-eel.ts.net:8129/message?token={{$env.GOTIFY_TOKEN}}",
        "sendBody": true,
        "contentType": "json",
        "bodyParameters": {
          "parameters": [
            { "name": "title", "value": "🚨 Backup Verification Failed" },
            { "name": "message", "value": "={{`Repo ${$json.repo} failed verification. Missing: ${$json.missing.join(', ')}. SHA: ${$json.headSha.slice(0,7)}`}}" },
            { "name": "priority", "value": "9" }
          ]
        },
        "options": { "timeout": 10000 }
      },
      "id": "notify-fail-gotify",
      "name": "Gotify Failure",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1600, 360]
    },
    {
      "parameters": {
        "chatId": "1793951355",
        "text": "={{`🦀 Backup verifier failed\nRepo: ${$json.repo}\nMissing: ${$json.missing.join(', ')}\nSHA: ${$json.headSha.slice(0,7)}`}}",
        "additionalFields": {}
      },
      "id": "notify-fail-telegram",
      "name": "Telegram Failure",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [1810, 360],
      "credentials": {
        "telegramApi": {
          "name": "Telegram account"
        }
      }
    }
  ],
  "connections": {
    "Daily 02:20 AWST": { "main": [[{ "node": "Set Context", "type": "main", "index": 0 }]] },
    "Set Context": { "main": [[{ "node": "Get Branch Head", "type": "main", "index": 0 }]] },
    "Get Branch Head": { "main": [[{ "node": "Get Repo Tree", "type": "main", "index": 0 }]] },
    "Get Repo Tree": { "main": [[{ "node": "Validate Required Files", "type": "main", "index": 0 }]] },
    "Validate Required Files": { "main": [[{ "node": "Backup OK?", "type": "main", "index": 0 }]] },
    "Backup OK?": {
      "main": [
        [{ "node": "Gotify Success", "type": "main", "index": 0 }],
        [{ "node": "Gotify Failure", "type": "main", "index": 0 }]
      ]
    },
    "Gotify Failure": { "main": [[{ "node": "Telegram Failure", "type": "main", "index": 0 }]] }
  },
  "settings": { "executionOrder": "v1" },
  "active": false
}
