{
  "id": "vw5o99SKHJVkNE4K",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Compliance Validation & Human Escalation System",
  "tags": [],
  "nodes": [
    {
      "id": "42f84a4b-4efe-48fe-b81b-417c34c77afa",
      "name": "\ud83d\udccc Overview \u2013 How This Workflow Works",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2272,
        672
      ],
      "parameters": {
        "width": 932,
        "height": 688,
        "content": "## \ud83d\udd0d AI Compliance Auditor \u2013 Two-Pass Record Screening\n\n### How it works\nA daily schedule reads all records from the `ComplianceRecords` sheet and sends each one through a two-pass AI review. Pass 1 (GPT-4o-mini) screens against four compliance rules: plaintext PII, undocumented high-value transactions, misclassified data, and missing mandatory regulatory fields. Records with no violation are marked Compliant immediately. Flagged records go to Pass 2, where a second AI call determines whether the flag is a false positive, an auto-fixable formatting issue, or a genuine violation that needs a human. Auto-fixes are written back to the sheet; anything requiring human judgment is escalated to the compliance team via Telegram. All outcomes \u2014 compliant, false positive, auto-fixed, and escalated \u2014 are merged and appended to the `AuditLog` sheet for a full daily audit trail.\n\n### Setup steps\n1. Connect **OpenAI API** to both AI nodes.\n2. Connect **Google Sheets OAuth2** and create a sheet with two tabs: `ComplianceRecords` and `AuditLog`. Replace `YOUR_GOOGLE_SHEET_ID` in all Sheets nodes.\n3. Connect **Telegram Bot API** and replace `YOUR_COMPLIANCE_TEAM_CHAT_ID` in the escalation node.\n4. Connect **Slack OAuth2** and replace `YOUR_SLACK_CHANNEL_ID` in both Slack error alert nodes.\n5. Adjust the schedule trigger to your preferred audit frequency.\n6. Activate the schedule trigger."
      },
      "typeVersion": 1
    },
    {
      "id": "bfc86c49-1f0e-4890-9047-ea9bc07dc607",
      "name": "Section \u2013 AI Pass 1 Compliance Screening",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -496,
        1424
      ],
      "parameters": {
        "color": 7,
        "width": 968,
        "height": 796,
        "content": "## \ud83e\udd16 AI Pass 1 \u2013 Compliance Screening\nChecks each record against four rules: plaintext PII, undocumented transactions above 10,000, misclassified data fields, and missing mandatory regulatory fields. Returns a violation flag, category, confidence score, and reasoning. The error output routes AI failures to Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "8dcded6e-282f-4f66-9cc4-6011cd2ac5f8",
      "name": "Section \u2013 Violation Gate",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        1088
      ],
      "parameters": {
        "color": 7,
        "width": 808,
        "height": 444,
        "content": "## \u2705 Violation Gate\nClean records are marked Compliant and routed straight to the final merge. Flagged records continue to Pass 2 for deeper analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "102226ab-4518-42ad-baa4-40c846f4c2f5",
      "name": "Section \u2013 AI Pass 2 Review & Resolution",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        1680
      ],
      "parameters": {
        "color": 7,
        "width": 1760,
        "height": 828,
        "content": "## \ud83d\udd2c AI Pass 2 \u2013 Review & Resolution\nA second AI call decides: false positive (dismiss), auto-fixable (write corrected value back to the sheet), or escalation needed (notify the compliance team via Telegram). Financial approvals, legal determinations, and anything irreversible are never auto-fixed \u2014 always escalated."
      },
      "typeVersion": 1
    },
    {
      "id": "a6b9b38d-5705-4758-a941-d0e58c331f19",
      "name": "Section \u2013 Merge & Audit Log",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2368,
        1136
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 604,
        "content": "## \ud83d\udccb Merge & Audit Log\nAll four outcome branches (Compliant, False Positive, Auto-Fixed, Escalated) merge here and are appended to the `AuditLog` sheet in a single pass, giving you a timestamped record of every decision made during the run."
      },
      "typeVersion": 1
    },
    {
      "id": "c054e67c-9fad-45d7-80bd-a93091e467f7",
      "name": "\ud83d\udd11 Credentials & Sheet Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2480,
        1936
      ],
      "parameters": {
        "color": 3,
        "width": 464,
        "height": 442,
        "content": "## \ud83d\udd11 Credentials Required\n- **OpenAI API** \u2014 both AI nodes\n- **Google Sheets OAuth2** \u2014 ComplianceRecords + AuditLog tabs\n- **Telegram Bot API** \u2014 compliance team escalations\n- **Slack OAuth2** \u2014 AI error alerts on both AI nodes\n\nSheet columns (ComplianceRecords): `RecordID, RecordType, DataField, Value, Description, Department, Status`\nSheet columns (AuditLog): `Timestamp, RecordID, Status, Category, Details`"
      },
      "typeVersion": 1
    },
    {
      "id": "040d3f4a-4251-453d-aab6-f1d8cc44f5db",
      "name": "AI Compliance Check - Pass 1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "onError": "continueErrorOutput",
      "position": [
        -384,
        1696
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {
          "temperature": 0.2
        },
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a compliance auditor AI. Check the given record against this rule set: 1) PII must not be stored in plaintext outside designated encrypted fields. 2) Financial transactions above 10,000 (in local currency) require a documented approval reference. 3) Data records must have a classification tag matching their actual content type. 4) Records must not be missing mandatory regulatory fields (e.g. tax ID, consent flag, KYC reference). Analyze the record and respond with ONLY a raw JSON object, no markdown, no extra text, in this exact shape: {\"violation_flagged\": boolean, \"category\": string, \"confidence\": number between 0 and 1, \"reasoning\": string}"
            },
            {
              "content": "=Record ID: {{ $json.RecordID }}\nRecord Type: {{ $json.RecordType }}\nField: {{ $json.DataField }}\nValue: {{ $json.Value }}\nDescription: {{ $json.Description }}\nDepartment: {{ $json.Department }}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "48dde1a7-a264-4e9a-a055-a39d8e4f228f",
      "name": "AI Verification & Auto-Fix - Pass 2",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "onError": "continueErrorOutput",
      "position": [
        656,
        2048
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {
          "temperature": 0.2
        },
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a senior compliance reviewer AI performing a second-pass review on a record already flagged by an initial screening. Your job: (1) Decide if this is a false positive given the full context. (2) If it is a genuine violation, decide if it is SAFELY auto-fixable without human sign-off - for example a misclassified data field, a formatting error, or a missing non-sensitive tag. (3) If auto-fixable, propose the exact corrected value. Never mark anything auto-fixable if it involves financial approval thresholds, legal or regulatory determinations, or anything irreversible - always escalate those instead. Respond with ONLY a raw JSON object, no markdown, no extra text, in this exact shape: {\"is_false_positive\": boolean, \"auto_fixable\": boolean, \"corrected_value\": string or null, \"escalation_reason\": string, \"summary\": string}"
            },
            {
              "content": "=Record ID: {{ $json.RecordID }}\nRecord Type: {{ $json.RecordType }}\nField: {{ $json.DataField }}\nValue: {{ $json.Value }}\nDescription: {{ $json.Description }}\nDepartment: {{ $json.Department }}\n\nInitial flag category: {{ $json.category }}\nInitial flag reasoning: {{ $json.reasoning }}\nInitial confidence: {{ $json.confidence }}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0d0f00a9-8944-4887-b8af-4667d5d6531a",
      "name": "Audit Trigger (Schedule)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1024,
        1696
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 24
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0499d06b-517a-4f96-bf1b-fc2082f5f410",
      "name": "Fetch Compliance Records",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -800,
        1696
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "ComplianceRecords"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "f8a09c73-f661-46a7-a033-d6c32c9de761",
      "name": "Parse Pass 1 Result",
      "type": "n8n-nodes-base.code",
      "position": [
        48,
        1680
      ],
      "parameters": {
        "jsCode": "const originalRecords = $('Fetch Compliance Records').all();\nconst aiResponses = $input.all();\nconst items = [];\n\nfor (let i = 0; i < aiResponses.length; i++) {\n  const original = originalRecords[i] ? originalRecords[i].json : {};\n  let raw = (aiResponses[i].json.message && aiResponses[i].json.message.content) || aiResponses[i].json.content || '';\n  raw = String(raw).trim().replace(/^```json\\s*/i, '').replace(/^```\\s*/i, '').replace(/```$/, '').trim();\n\n  let parsed;\n  try {\n    parsed = JSON.parse(raw);\n  } catch (e) {\n    parsed = {\n      violation_flagged: true,\n      category: 'parse_error',\n      confidence: 0,\n      reasoning: 'Could not parse AI response, escalating by default: ' + raw.slice(0, 200)\n    };\n  }\n\n  items.push({\n    json: {\n      ...original,\n      violation_flagged: parsed.violation_flagged === true,\n      category: parsed.category || 'unknown',\n      confidence: parsed.confidence !== undefined ? parsed.confidence : null,\n      reasoning: parsed.reasoning || ''\n    }\n  });\n}\n\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "a561e0f6-5900-4d14-b9f3-6dc22545210f",
      "name": "Violation Flagged?",
      "type": "n8n-nodes-base.if",
      "position": [
        272,
        1680
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-violation",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.violation_flagged }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "994de343-178c-4835-ac43-b572df0b0dc2",
      "name": "Mark Compliant",
      "type": "n8n-nodes-base.set",
      "position": [
        928,
        1280
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "Status",
              "type": "string",
              "value": "Compliant"
            },
            {
              "id": "a2",
              "name": "Details",
              "type": "string",
              "value": "=No violation detected (confidence: {{ $json.confidence }})"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c77eee55-42d2-42bf-8b68-5cad67a5824a",
      "name": "Parse Pass 2 Result",
      "type": "n8n-nodes-base.code",
      "position": [
        1040,
        2016
      ],
      "parameters": {
        "jsCode": "const flaggedRecords = $('Parse Pass 1 Result').all();\nconst aiResponses = $input.all();\nconst items = [];\n\nfor (let i = 0; i < aiResponses.length; i++) {\n  const original = flaggedRecords[i] ? flaggedRecords[i].json : {};\n  let raw = (aiResponses[i].json.message && aiResponses[i].json.message.content) || aiResponses[i].json.content || '';\n  raw = String(raw).trim().replace(/^```json\\s*/i, '').replace(/^```\\s*/i, '').replace(/```$/, '').trim();\n\n  let parsed;\n  try {\n    parsed = JSON.parse(raw);\n  } catch (e) {\n    parsed = {\n      is_false_positive: false,\n      auto_fixable: false,\n      corrected_value: null,\n      escalation_reason: 'Could not parse pass 2 AI response, escalating by default: ' + raw.slice(0, 200),\n      summary: 'Parse error on second pass review.'\n    };\n  }\n\n  items.push({\n    json: {\n      ...original,\n      is_false_positive: parsed.is_false_positive === true,\n      auto_fixable: parsed.auto_fixable === true,\n      corrected_value: parsed.corrected_value || null,\n      escalation_reason: parsed.escalation_reason || '',\n      summary: parsed.summary || ''\n    }\n  });\n}\n\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "24ae8872-2ce7-4f1e-a2c7-cd8c3d17260a",
      "name": "False Positive?",
      "type": "n8n-nodes-base.if",
      "position": [
        1248,
        2016
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-fp",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.is_false_positive }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5428b270-9c06-4a99-915c-ab924ca9ccef",
      "name": "Mark False Positive Resolved",
      "type": "n8n-nodes-base.set",
      "position": [
        1472,
        1872
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "Status",
              "type": "string",
              "value": "False Positive - Resolved"
            },
            {
              "id": "a2",
              "name": "Details",
              "type": "string",
              "value": "={{ $json.summary }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b3b2ce6b-142b-447f-ac86-204476913828",
      "name": "Auto-Fixable?",
      "type": "n8n-nodes-base.if",
      "position": [
        1472,
        2144
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-autofix",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.auto_fixable }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9834a45c-dd90-402f-9251-49ac2f28261f",
      "name": "Apply Auto-Fix",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1696,
        2048
      ],
      "parameters": {
        "columns": {
          "value": {
            "Value": "={{ $json.corrected_value }}",
            "Status": "Auto-Fixed",
            "RecordID": "={{ $json.RecordID }}",
            "row_number": 0
          },
          "schema": [
            {
              "id": "RecordID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "RecordID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RecordType",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "RecordType",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DataField",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DataField",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Value",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Value",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Department",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Department",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "RecordID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "ComplianceRecords"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "dac13217-0d7d-4b70-a7e1-55125e7c78f0",
      "name": "Prepare Auto-Fix Log",
      "type": "n8n-nodes-base.set",
      "position": [
        1920,
        2048
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "Status",
              "type": "string",
              "value": "Auto-Fixed"
            },
            {
              "id": "a2",
              "name": "Details",
              "type": "string",
              "value": "=Corrected value applied: {{ $json.corrected_value }}. Summary: {{ $json.summary }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a7cb62c6-0ef2-47cd-8dd4-e1fac7e07ecb",
      "name": "Escalate to Compliance Team",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1696,
        2256
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f Compliance Escalation Needed\n\nRecord ID: {{ $json.RecordID }}\nCategory: {{ $json.category }}\nReasoning: {{ $json.reasoning }}\nWhy it couldn't be auto-resolved: {{ $json.escalation_reason }}\n\nPlease review manually.",
        "chatId": "YOUR_COMPLIANCE_TEAM_CHAT_ID",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "11c143e4-3323-443d-8759-1ea96077de95",
      "name": "Prepare Escalation Log",
      "type": "n8n-nodes-base.set",
      "position": [
        1920,
        2256
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "Status",
              "type": "string",
              "value": "Escalated to Human"
            },
            {
              "id": "a2",
              "name": "Details",
              "type": "string",
              "value": "={{ $json.escalation_reason }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f2789ebb-bb2e-4345-aa75-8b83a3a718f5",
      "name": "Combine Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        2528,
        1392
      ],
      "parameters": {
        "numberInputs": 4
      },
      "typeVersion": 3.1
    },
    {
      "id": "181b3e1c-82d5-4c3c-badd-b594185ed940",
      "name": "Append to Audit Log",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2848,
        1424
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ $json.Status }}",
            "Details": "={{ $json.Details }}",
            "Category": "={{ $json.category }}",
            "RecordID": "={{ $json.RecordID }}",
            "Timestamp": "={{ $now.toISO() }}"
          },
          "schema": [
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RecordID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "RecordID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Details",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Details",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "AuditLog"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "542f83d6-3d86-4855-ad8d-885fb96d3e2c",
      "name": "Slack \u2014 Send Workflow Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        64,
        1920
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f AI Compliance Check - Pass 1 failed\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "your-alerts-channel"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "af74f159-71f0-4c4f-accb-0895edb799ee",
      "name": "Slack \u2014 Send Pass 2 Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        1040,
        2208
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f AI Verification - Pass 2 failed\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "your-alerts-channel"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "027fd6fc-e079-4872-8205-2b9086d9ef0e",
      "name": "Section \u2013 Error Handling",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        2560
      ],
      "parameters": {
        "color": 7,
        "width": 748,
        "height": 488,
        "content": "## \u26a0\ufe0f Error Handling\nThree Slack alerts catch failures: a global error trigger covers the whole workflow, and the two AI nodes each have a dedicated error output wired to Slack. Update the channel ID and improve the alert message with context before going live."
      },
      "typeVersion": 1
    },
    {
      "id": "0c7d17ad-ccbb-42a5-b736-2ed6d8085ff9",
      "name": "On Workflow Error",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -688,
        2800
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "0c221e50-1332-40eb-bc21-eaefb67a4e45",
      "name": "Slack \u2013 Post Workflow Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        -416,
        2800
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *DentalOS Workflow Error*\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}\n*Execution ID:* {{ $execution.id }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "your-alerts-channel"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "8bc3a747-2c22-403d-a427-50f139b0bc5e",
      "name": "Section \u2013 Trigger & Data Fetch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1152,
        1440
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 572,
        "content": "## \u23f0 Trigger & Data Fetch\nRuns on a daily schedule and reads all rows from the `ComplianceRecords` sheet. Each row is a separate record that flows independently through the rest of the pipeline."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "5559d23e-49f3-49c6-aaf7-d356d37556ab",
  "nodeGroups": [],
  "connections": {
    "Auto-Fixable?": {
      "main": [
        [
          {
            "node": "Apply Auto-Fix",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Escalate to Compliance Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Apply Auto-Fix": {
      "main": [
        [
          {
            "node": "Prepare Auto-Fix Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Compliant": {
      "main": [
        [
          {
            "node": "Combine Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Results": {
      "main": [
        [
          {
            "node": "Append to Audit Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "False Positive?": {
      "main": [
        [
          {
            "node": "Mark False Positive Resolved",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Auto-Fixable?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On Workflow Error": {
      "main": [
        [
          {
            "node": "Slack \u2013 Post Workflow Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Violation Flagged?": {
      "main": [
        [
          {
            "node": "AI Verification & Auto-Fix - Pass 2",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Compliant",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Pass 1 Result": {
      "main": [
        [
          {
            "node": "Violation Flagged?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Pass 2 Result": {
      "main": [
        [
          {
            "node": "False Positive?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Auto-Fix Log": {
      "main": [
        [
          {
            "node": "Combine Results",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Prepare Escalation Log": {
      "main": [
        [
          {
            "node": "Combine Results",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Audit Trigger (Schedule)": {
      "main": [
        [
          {
            "node": "Fetch Compliance Records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Compliance Records": {
      "main": [
        [
          {
            "node": "AI Compliance Check - Pass 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Escalate to Compliance Team": {
      "main": [
        [
          {
            "node": "Prepare Escalation Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Compliance Check - Pass 1": {
      "main": [
        [
          {
            "node": "Parse Pass 1 Result",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack \u2014 Send Workflow Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark False Positive Resolved": {
      "main": [
        [
          {
            "node": "Combine Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Slack \u2014 Send Pass 2 Error Alert": {
      "main": [
        [
          {
            "node": "Violation Flagged?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Verification & Auto-Fix - Pass 2": {
      "main": [
        [
          {
            "node": "Parse Pass 2 Result",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack \u2014 Send Pass 2 Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack \u2014 Send Workflow Error Alert": {
      "main": [
        [
          {
            "node": "Fetch Compliance Records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}