{
  "name": "HIPAA-Compliant Healthcare Data Synchronization",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "name": "Schedule Sync",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "// Initialize audit log\nconst auditLog = {\n  syncId: crypto.randomUUID(),\n  timestamp: new Date().toISOString(),\n  environment: process.env.NODE_ENV || 'production',\n  syncType: 'scheduled',\n  complianceChecks: {\n    encryption: true,\n    authentication: true,\n    authorization: true,\n    dataMinimization: true\n  },\n  piiAccessed: [],\n  startTime: Date.now()\n};\n\n// Store audit log in execution data\nglobal.currentAudit = auditLog;\n\nreturn [{ json: { auditLog } }];"
      },
      "name": "Initialize Audit",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "fhirApi",
        "requestMethod": "GET",
        "url": "https://ehr-system.hospital.com/fhir/Patient",
        "options": {
          "headers": {
            "entries": [
              {
                "name": "X-Audit-User",
                "value": "sync-service"
              },
              {
                "name": "X-Purpose-Of-Use",
                "value": "TREATMENT"
              }
            ]
          },
          "timeout": 30000
        },
        "queryParametersUi": {
          "parameter": [
            {
              "name": "_lastUpdated",
              "value": "gt{{ $now.minus(15, 'minutes').toISO() }}"
            },
            {
              "name": "_count",
              "value": "100"
            }
          ]
        }
      },
      "name": "Fetch EHR Updates",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        650,
        200
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT patient_id, last_sync_timestamp FROM patient_sync_status WHERE needs_update = true LIMIT 100"
      },
      "name": "Get Pending Syncs",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        650,
        400
      ]
    },
    {
      "parameters": {
        "functionCode": "// Parse FHIR bundle and extract patient data\nconst ehrData = $node['Fetch EHR Updates'].json;\nconst pendingSyncs = $node['Get Pending Syncs'].json;\n\nconst patients = [];\nconst errors = [];\n\n// Process FHIR bundle\nif (ehrData.resourceType === 'Bundle' && ehrData.entry) {\n  for (const entry of ehrData.entry) {\n    try {\n      const patient = entry.resource;\n      if (patient.resourceType !== 'Patient') continue;\n      \n      // De-identify data for analytics\n      const deIdentified = {\n        patientId: patient.id,\n        mrn: patient.identifier?.find(id => id.system === 'MRN')?.value,\n        demographics: {\n          birthYear: patient.birthDate ? new Date(patient.birthDate).getFullYear() : null,\n          gender: patient.gender,\n          zipCode: patient.address?.[0]?.postalCode?.substring(0, 3) + 'XX' // First 3 digits only\n        },\n        lastUpdated: patient.meta?.lastUpdated\n      };\n      \n      // Encrypt sensitive fields\n      const encrypted = {\n        ...deIdentified,\n        name: encrypt(JSON.stringify(patient.name)),\n        fullAddress: encrypt(JSON.stringify(patient.address)),\n        telecom: encrypt(JSON.stringify(patient.telecom)),\n        ssn: patient.identifier?.find(id => id.system === 'SSN') \n          ? encrypt(patient.identifier.find(id => id.system === 'SSN').value)\n          : null\n      };\n      \n      patients.push(encrypted);\n      \n      // Log PII access for audit\n      global.currentAudit.piiAccessed.push({\n        patientId: patient.id,\n        fieldsAccessed: ['name', 'address', 'telecom', 'ssn'],\n        timestamp: new Date().toISOString(),\n        purpose: 'sync'\n      });\n      \n    } catch (error) {\n      errors.push({\n        resourceId: entry.resource?.id,\n        error: error.message,\n        timestamp: new Date().toISOString()\n      });\n    }\n  }\n}\n\n// Mock encryption function\nfunction encrypt(data) {\n  return Buffer.from(data).toString('base64');\n}\n\nreturn [\n  patients.map(p => ({json: p})),\n  errors.map(e => ({json: e}))\n];"
      },
      "name": "Process & Encrypt",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $items().length }}",
              "operation": "larger",
              "value2": 0
            }
          ]
        }
      },
      "name": "Has Patients?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1050,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $items().length }}",
              "operation": "larger",
              "value2": 0
            }
          ]
        }
      },
      "name": "Has Errors?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1050,
        400
      ]
    },
    {
      "parameters": {
        "functionCode": "// Validate data integrity before syncing\nconst validPatients = [];\nconst validationErrors = [];\n\nfor (const item of items) {\n  const patient = item.json;\n  const validationResult = {\n    patientId: patient.patientId,\n    checks: {\n      hasRequiredFields: !!(patient.patientId && patient.mrn),\n      encryptionValid: !!(patient.name && patient.fullAddress && patient.telecom),\n      dataIntegrity: validateChecksum(patient),\n      consentOnFile: await checkConsent(patient.patientId)\n    }\n  };\n  \n  const allChecksPassed = Object.values(validationResult.checks).every(v => v);\n  \n  if (allChecksPassed) {\n    validPatients.push(patient);\n  } else {\n    validationErrors.push({\n      ...patient,\n      validationResult,\n      action: 'quarantine'\n    });\n  }\n}\n\n// Mock functions\nfunction validateChecksum(data) {\n  // In production, would calculate and verify checksum\n  return true;\n}\n\nasync function checkConsent(patientId) {\n  // In production, would check consent database\n  return true;\n}\n\nreturn [\n  validPatients.map(p => ({json: p})),\n  validationErrors.map(e => ({json: e}))\n];"
      },
      "name": "Validate Integrity",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1250,
        200
      ]
    },
    {
      "parameters": {
        "operation": "upsert",
        "table": "patient_analytics",
        "columns": "patient_id,mrn,demographics,last_updated,encrypted_pii",
        "updateKey": "patient_id",
        "options": {
          "queryBatching": "transaction"
        }
      },
      "name": "Sync to Analytics DB",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1450,
        100
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": "={{ $json.patientId }}",
        "collection": "patients",
        "updateFields": "={{ JSON.stringify($json) }}",
        "options": {
          "upsert": true
        }
      },
      "name": "Sync to NoSQL",
      "type": "n8n-nodes-base.mongoDb",
      "typeVersion": 1,
      "position": [
        1450,
        200
      ]
    },
    {
      "parameters": {
        "operation": "create",
        "index": "patient-search",
        "documentId": "={{ $json.patientId }}",
        "body": "={{ JSON.stringify({...($json), indexed_at: new Date().toISOString()}) }}"
      },
      "name": "Update Search Index",
      "type": "n8n-nodes-base.elasticsearch",
      "typeVersion": 1,
      "position": [
        1450,
        300
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO data_quarantine (patient_id, data, reason, timestamp) VALUES ($1, $2, $3, $4)",
        "options": {
          "queryParams": "={{ $json.patientId }},={{ JSON.stringify($json) }},={{ JSON.stringify($json.validationResult) }},={{ new Date().toISOString() }}"
        }
      },
      "name": "Quarantine Invalid",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1450,
        400
      ]
    },
    {
      "parameters": {
        "level": "error",
        "message": "Healthcare sync error",
        "fields": {
          "item": [
            {
              "name": "syncId",
              "value": "={{ global.currentAudit.syncId }}"
            },
            {
              "name": "errorCount",
              "value": "={{ $items().length }}"
            },
            {
              "name": "errors",
              "value": "={{ JSON.stringify($items().map(i => i.json)) }}"
            }
          ]
        }
      },
      "name": "Log Sync Errors",
      "type": "n8n-nodes-base.syslog",
      "typeVersion": 1,
      "position": [
        1250,
        500
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE patient_sync_status SET last_sync_timestamp = NOW(), sync_status = $1 WHERE patient_id = ANY($2)",
        "options": {
          "queryParams": "success,={{ $items().map(i => i.json.patientId) }}"
        }
      },
      "name": "Update Sync Status",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1650,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "// Generate compliance report\nconst audit = global.currentAudit;\naudit.endTime = Date.now();\naudit.duration = audit.endTime - audit.startTime;\n\nconst successCount = $node['Has Patients?'].json?.length || 0;\nconst errorCount = $node['Has Errors?'].json?.length || 0;\nconst quarantineCount = $node['Quarantine Invalid'].json?.length || 0;\n\nconst report = {\n  syncId: audit.syncId,\n  timestamp: audit.timestamp,\n  summary: {\n    totalProcessed: successCount + errorCount + quarantineCount,\n    successful: successCount,\n    errors: errorCount,\n    quarantined: quarantineCount,\n    duration: audit.duration\n  },\n  compliance: {\n    ...audit.complianceChecks,\n    piiAccessLogged: audit.piiAccessed.length > 0,\n    encryptionUsed: true,\n    auditTrailComplete: true\n  },\n  dataAccess: {\n    patientsAccessed: audit.piiAccessed.length,\n    fieldsAccessed: ['name', 'address', 'telecom', 'ssn'],\n    purpose: 'TREATMENT',\n    retention: '7 years'\n  },\n  nextSync: new Date(Date.now() + 900000).toISOString() // 15 minutes\n};\n\nreturn [{ json: report }];"
      },
      "name": "Generate Compliance Report",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1850,
        300
      ]
    },
    {
      "parameters": {
        "operation": "create",
        "table": "hipaa_audit_log",
        "columns": "sync_id,timestamp,summary,compliance,data_access,user_id,purpose"
      },
      "name": "Store Audit Log",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        2050,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.summary.errors }}",
              "operation": "larger",
              "value2": 5
            }
          ],
          "boolean": [
            {
              "value1": "={{ $json.compliance.auditTrailComplete }}",
              "value2": false
            }
          ]
        },
        "combineOperation": "any"
      },
      "name": "Alert Needed?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        2250,
        300
      ]
    },
    {
      "parameters": {
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "pagerDutyApi",
        "requestMethod": "POST",
        "url": "https://events.pagerduty.com/v2/enqueue",
        "jsonParameters": true,
        "options": {},
        "bodyParametersJson": "{\n  \"routing_key\": \"healthcare-sync-service\",\n  \"event_action\": \"trigger\",\n  \"payload\": {\n    \"summary\": \"Healthcare sync issues detected\",\n    \"severity\": \"error\",\n    \"source\": \"n8n-sync\",\n    \"custom_details\": {{ JSON.stringify($json) }}\n  }\n}"
      },
      "name": "Page On-Call",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        2450,
        200
      ]
    },
    {
      "parameters": {
        "fromEmail": "compliance@hospital.com",
        "toEmail": "compliance-team@hospital.com",
        "subject": "Healthcare Data Sync Report - {{ $json.syncId }}",
        "html": "<h2>HIPAA Compliance Report</h2>\n<p>Sync ID: {{ $json.syncId }}</p>\n<p>Timestamp: {{ $json.timestamp }}</p>\n<h3>Summary</h3>\n<ul>\n  <li>Total Processed: {{ $json.summary.totalProcessed }}</li>\n  <li>Successful: {{ $json.summary.successful }}</li>\n  <li>Errors: {{ $json.summary.errors }}</li>\n  <li>Quarantined: {{ $json.summary.quarantined }}</li>\n  <li>Duration: {{ $json.summary.duration }}ms</li>\n</ul>\n<h3>Compliance Status</h3>\n<p>All compliance checks: {{ $json.compliance }}</p>\n<h3>Next Sync</h3>\n<p>{{ $json.nextSync }}</p>",
        "options": {
          "allowUnauthorizedCerts": false
        }
      },
      "name": "Email Compliance Report",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2,
      "position": [
        2250,
        400
      ]
    }
  ],
  "connections": {
    "Schedule Sync": {
      "main": [
        [
          {
            "node": "Initialize Audit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initialize Audit": {
      "main": [
        [
          {
            "node": "Fetch EHR Updates",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Pending Syncs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch EHR Updates": {
      "main": [
        [
          {
            "node": "Process & Encrypt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Pending Syncs": {
      "main": [
        [
          {
            "node": "Process & Encrypt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process & Encrypt": {
      "main": [
        [
          {
            "node": "Has Patients?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Has Errors?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Patients?": {
      "main": [
        [
          {
            "node": "Validate Integrity",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Has Errors?": {
      "main": [
        [
          {
            "node": "Log Sync Errors",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Validate Integrity": {
      "main": [
        [
          {
            "node": "Sync to Analytics DB",
            "type": "main",
            "index": 0
          },
          {
            "node": "Sync to NoSQL",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update Search Index",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Quarantine Invalid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sync to Analytics DB": {
      "main": [
        [
          {
            "node": "Update Sync Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sync to NoSQL": {
      "main": [
        [
          {
            "node": "Update Sync Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Search Index": {
      "main": [
        [
          {
            "node": "Update Sync Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Sync Status": {
      "main": [
        [
          {
            "node": "Generate Compliance Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Sync Errors": {
      "main": [
        [
          {
            "node": "Generate Compliance Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Quarantine Invalid": {
      "main": [
        [
          {
            "node": "Generate Compliance Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Compliance Report": {
      "main": [
        [
          {
            "node": "Store Audit Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Audit Log": {
      "main": [
        [
          {
            "node": "Alert Needed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alert Needed?": {
      "main": [
        [
          {
            "node": "Page On-Call",
            "type": "main",
            "index": 0
          },
          {
            "node": "Email Compliance Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Compliance Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}