{
  "name": "Invoice-to-Pay (governed) — willytai.com Living RCM",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "invoice-inbox",
        "options": {}
      },
      "id": "a1b2c3d4-0001-4000-8000-000000000001",
      "name": "Invoice received (external input)",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [-380, 60]
    },
    {
      "parameters": {
        "jsCode": "// S1 — Capture & extract (agent AGT-EXTRACT-01, TACO: Tasker)\n// In production this calls a vision model with a SCHEMA-CONSTRAINED prompt (control C1):\n// the model may only emit typed, allow-listed fields — free text in the source\n// cannot become an output field. Stubbed here so the workflow imports and runs anywhere.\nconst invoice = $input.first().json;\nreturn [{ json: {\n  vendor: invoice.vendor ?? 'ACME Pte Ltd',\n  invoice_no: invoice.invoice_no ?? 'INV-2026-0001',\n  currency: invoice.currency ?? 'SGD',\n  amount: invoice.amount ?? 8450.00,\n  line_items: invoice.line_items ?? [ { desc: 'Services', qty: 1, unit: 8450.00 } ],\n  bank_last4: invoice.bank_last4 ?? '4417'\n}}];"
      },
      "id": "a1b2c3d4-0002-4000-8000-000000000002",
      "name": "S1 · Extract fields (AI agent, schema-fenced)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [-140, 60]
    },
    {
      "parameters": {
        "jsCode": "// Control C2 — deterministic reconciliation gate (detective, automated).\n// CODE re-adds the line items and checks the stated total. The model never\n// certifies its own arithmetic. A mismatch routes to human review, not onward.\nconst x = $input.first().json;\nconst sum = (x.line_items || []).reduce((a, li) => a + li.qty * li.unit, 0);\nconst tol = Math.max(0.02 * x.amount, 0.05);\nconst reconciled = Math.abs(sum - x.amount) <= tol;\nreturn [{ json: { ...x, reconciled, line_sum: sum } }];"
      },
      "id": "a1b2c3d4-0003-4000-8000-000000000003",
      "name": "C2 · Reconciliation gate (deterministic)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [100, 60]
    },
    {
      "parameters": {
        "conditions": {
          "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
          "conditions": [
            {
              "id": "cond-recon",
              "leftValue": "={{ $json.reconciled }}",
              "rightValue": true,
              "operator": { "type": "boolean", "operation": "equals" }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "a1b2c3d4-0004-4000-8000-000000000004",
      "name": "S2 · Three-way match ok?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [340, 60]
    },
    {
      "parameters": {
        "conditions": {
          "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
          "conditions": [
            {
              "id": "cond-amount",
              "leftValue": "={{ $json.amount }}",
              "rightValue": 10000,
              "operator": { "type": "number", "operation": "gte" }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "a1b2c3d4-0005-4000-8000-000000000005",
      "name": "S3 · Amount ≥ S$10k? (authority matrix C8)",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [580, 20]
    },
    {
      "parameters": {},
      "id": "a1b2c3d4-0006-4000-8000-000000000006",
      "name": "C9 · Dual approval — two named approvers (HITL)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [820, -60]
    },
    {
      "parameters": {},
      "id": "a1b2c3d4-0007-4000-8000-000000000007",
      "name": "Single approval — named approver (HITL)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [820, 100]
    },
    {
      "parameters": {},
      "id": "a1b2c3d4-0008-4000-8000-000000000008",
      "name": "Exception queue — human review (HOTL)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [580, 220]
    },
    {
      "parameters": {
        "jsCode": "// S4 — Post & pay (agent AGT-POST-01, TACO: Automator).\n// Controls: C12 idempotency key (a run executed twice pays once);\n// C13 auto-reversal on failed posting (corrective); C11 pre-release\n// reconciliation is the human controller's step before bank release.\nconst x = $input.first().json;\nreturn [{ json: { ...x, posted: true, idempotency_key: `${x.vendor}|${x.invoice_no}|${x.amount}` } }];"
      },
      "id": "a1b2c3d4-0009-4000-8000-000000000009",
      "name": "S4 · Post to ledger + payment run",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1060, 20]
    },
    {
      "parameters": {
        "jsCode": "// Control C14 — hash-chained action ledger (detective, automated).\n// EVERY action appends an entry carrying unique identifiers for the AGENT and\n// the HUMAN (KPMG agentic-AI control considerations #5–6): attributable,\n// append-only, replayable. In production this posts to the control plane;\n// here it shapes the entry so the import demonstrates the pattern.\nconst x = $input.first().json;\nreturn [{ json: {\n  ledger_entry: {\n    action: 'post_and_pay',\n    txn: x.invoice_no,\n    agent_id: 'AGT-POST-01',\n    human_id: 'USR-CONTROLLER-01',\n    amount: x.amount,\n    prev_hash: '<chained>',\n    note: 'append-only · hash-chained · replayable'\n  }\n}}];"
      },
      "id": "a1b2c3d4-0010-4000-8000-000000000010",
      "name": "C14 · Append to hash-chained ledger",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1300, 20]
    },
    {
      "parameters": {
        "content": "## The Living RCM — governance annotations\n\nThis workflow is the orchestration skeleton of the Living RCM demo at willytai.com/apps/living-rcm/.\n\n**Trust boundary:** deterministic code decides (match, thresholds, routing); the model only extracts and phrases. Humans hold the consequential decisions (approval, bank release).\n\n**Risk lifecycle per step** (inherent → controls → residual, 5-pt COSO scales):\n- S1 extract · R1 misread field L4×I4 → C1 schema fence + C2 recon gate → L2×I4\n- S1 extract · R2 prompt injection L3×I4 → C1 + C3 anomaly alert → L1×I4\n- S2 match · R3 duplicate passes L3×I4 → C4 dup-hash + C5 3-way match → L1×I3\n- S3 approve · R6 dual-approval bypass L2×I5 → C9 + C10 SoD → L1×I5 (tested every cycle)\n- S4 pay · R7 wrong payment released L3×I5 → C11 + C12 + C13 → L1×I4\n\nFull RCM, ratings, citations and the IIA-style audit: the live demo.",
        "height": 420,
        "width": 460
      },
      "id": "a1b2c3d4-0011-4000-8000-000000000011",
      "name": "Sticky Note — RCM",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [-380, -420]
    }
  ],
  "connections": {
    "Invoice received (external input)": {
      "main": [
        [ { "node": "S1 · Extract fields (AI agent, schema-fenced)", "type": "main", "index": 0 } ]
      ]
    },
    "S1 · Extract fields (AI agent, schema-fenced)": {
      "main": [
        [ { "node": "C2 · Reconciliation gate (deterministic)", "type": "main", "index": 0 } ]
      ]
    },
    "C2 · Reconciliation gate (deterministic)": {
      "main": [
        [ { "node": "S2 · Three-way match ok?", "type": "main", "index": 0 } ]
      ]
    },
    "S2 · Three-way match ok?": {
      "main": [
        [ { "node": "S3 · Amount ≥ S$10k? (authority matrix C8)", "type": "main", "index": 0 } ],
        [ { "node": "Exception queue — human review (HOTL)", "type": "main", "index": 0 } ]
      ]
    },
    "S3 · Amount ≥ S$10k? (authority matrix C8)": {
      "main": [
        [ { "node": "C9 · Dual approval — two named approvers (HITL)", "type": "main", "index": 0 } ],
        [ { "node": "Single approval — named approver (HITL)", "type": "main", "index": 0 } ]
      ]
    },
    "C9 · Dual approval — two named approvers (HITL)": {
      "main": [
        [ { "node": "S4 · Post to ledger + payment run", "type": "main", "index": 0 } ]
      ]
    },
    "Single approval — named approver (HITL)": {
      "main": [
        [ { "node": "S4 · Post to ledger + payment run", "type": "main", "index": 0 } ]
      ]
    },
    "S4 · Post to ledger + payment run": {
      "main": [
        [ { "node": "C14 · Append to hash-chained ledger", "type": "main", "index": 0 } ]
      ]
    }
  },
  "settings": { "executionOrder": "v1" },
  "pinData": {},
  "meta": { "instanceId": "willytai-living-rcm-demo" }
}
