{
  "name": "REVOPS-LI-007 | 07 | Proposal recovery operations",
  "nodes": [
    {
      "parameters": {},
      "id": "3da9ab6a-7d39-4c45-b0de-6838b2501560",
      "name": "Proposal Workflow Error",
      "type": "n8n-nodes-base.errorTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const e=$input.first().json;return [{json:{execution_id:String(e.execution?.id||''),workflow:String(e.workflow?.name||''),node:String(e.execution?.lastNodeExecuted||''),message:String(e.execution?.error?.message||'failed').replace(/Bearer\\s+\\S+/gi,'Bearer [REDACTED]').slice(0,1000)}}];"
      },
      "id": "106c112c-d09f-4c5d-8d8d-67389b3c3d4e",
      "name": "Redact Failure",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        270,
        0
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT ghosted_proposal.fail_execution($1::text,$2::jsonb);",
        "options": {
          "queryReplacement": "={{ [$json.execution_id,JSON.stringify($json)] }}"
        }
      },
      "id": "f304acdc-537f-4f69-ab1a-fe237382b27c",
      "name": "Record Failure",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        540,
        0
      ],
      "credentials": {
        "postgres": {
          "id": "REPLACE_POSTGRES_CREDENTIAL",
          "name": "ATTRIBUTION Postgres"
        }
      }
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "id": "c219bfc1-026f-43de-bab2-82e54d99ed41",
      "name": "Inspect Recovery Health",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        810,
        0
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT status,count(*) AS records,min(updated_at) AS oldest FROM ghosted_proposal.cases GROUP BY status UNION ALL SELECT 'REPLY_'||status,count(*),min(updated_at) FROM ghosted_proposal.reply_events GROUP BY status;",
        "options": {
          "queryReplacement": "={{ [] }}"
        }
      },
      "id": "ee77d569-abd3-4365-90e4-d1cb3be51b49",
      "name": "Return Status Counts",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1080,
        0
      ],
      "credentials": {
        "postgres": {
          "id": "REPLACE_POSTGRES_CREDENTIAL",
          "name": "ATTRIBUTION Postgres"
        }
      }
    },
    {
      "parameters": {
        "content": "## Operations\nSelect this as Error Workflow for workflows 01, 02, 04 and 05.\nA failed or stale SENDING case is held for manual reconciliation and never automatically resent. Review counts expose approvals, manual tasks, blocked sends, and reply failures.",
        "width": 700,
        "height": 220
      },
      "id": "134d0038-b5a7-4163-acbd-6b6031c343e6",
      "name": "Workflow Guide",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -270
      ]
    }
  ],
  "connections": {
    "Proposal Workflow Error": {
      "main": [
        [
          {
            "node": "Redact Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Redact Failure": {
      "main": [
        [
          {
            "node": "Record Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Inspect Recovery Health": {
      "main": [
        [
          {
            "node": "Return Status Counts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "timezone": "Asia/Tbilisi",
    "saveExecutionProgress": true
  },
  "active": false,
  "pinData": {},
  "tags": []
}
