If your HRTech or Workforce SaaS platform processes payroll data, leave requests, accommodation forms, or I-9 documents for employer customers — your automation layer is inside a compliance boundary most vendors don't realize they've crossed.
The core problem: Employee payroll records (FLSA §211), FMLA medical certifications (§825.500), ADA medical information (42 USC §12112(d)(3)), and I-9 documents (8 USC §1324a) all carry federal confidentiality requirements. If your platform routes any of this data through a cloud iPaaS (Zapier, Make, Workato) to trigger workflows, that iPaaS becomes an undocumented subprocessor processing federally-protected employee data — without a BAA, DPA, or disclosure in your customer's privacy notice.
Self-hosted n8n deployed inside your customers' security perimeters eliminates this entirely. Here are 5 workflows every HRTech and Workforce SaaS vendor needs.
The 7 HRTech & Workforce SaaS Customer Tiers
| Tier | Profile | Primary Frameworks |
|---|---|---|
| ENTERPRISE_HCM_PLATFORM | Large HCM vendors (Workday-tier) | FLSA, FMLA, ADA, EEOC, I-9, WARN, state laws |
| MIDMARKET_PAYROLL_SAAS | Payroll platforms for 50-500 employee companies | FLSA §206-207, §211 recordkeeping, state wage laws |
| WORKFORCE_MANAGEMENT_SAAS | Time-tracking, scheduling, shift management | FLSA overtime calculation, break law compliance |
| TALENT_ACQUISITION_SAAS | ATS, sourcing, background check platforms | EEOC Title VII, FCRA §604, state ban-the-box laws |
| LEAVE_MANAGEMENT_SAAS | FMLA, PTO, disability leave tracking | FMLA 29 CFR §825, ADA, state PFML laws |
| BENEFITS_ADMIN_SAAS | 401(k), health insurance, FSA/HSA platforms | ERISA §404, HIPAA for health data, IRS §125 |
| HRTECH_STARTUP | Early-stage workforce tools | CCPA/CPRA employee data, basic FLSA/ADA |
The 7 Compliance Flags Your Onboarding Must Detect
| Flag | What It Activates |
|---|---|
| FLSA_OVERTIME_SUBJECT | 3yr willful back-pay clock + DOL audit recordkeeping — payroll records cannot transit cloud iPaaS |
| FMLA_EMPLOYER_COVERED | 5-day designation notice clock + §825.500 medical confidentiality — FMLA certifications require separate confidential file |
| ADA_TITLE_I_SUBJECT | Immediate interactive process obligation + §12112(d)(3) medical info separate file requirement |
| EEOC_CHARGE_HANDLER | 180-day investigation window — charge documentation contains employee complaints under privilege |
| I9_EMPLOYER_COMPLIANT | 3-business-day ICE audit response + 3yr/1yr retention — I-9 documents cannot route through undocumented subprocessors |
| WARN_ACT_SUBJECT | 60-day advance notice before mass layoff — 100+ employees or 50+ job losses at single site |
| CCPA_CPRA_EMPLOYEE_DATA | 45-day employee data request response — CPRA fully covers employees as of January 2023 |
The 8 Incident Types (Fastest First)
| Incident | Deadline | Regulatory Basis |
|---|---|---|
| ADA_FMLA_LEAVE_REQUEST_RECEIVED | Immediate interactive process | 42 USC §12112(b)(5) + 29 CFR §825.300 |
| I9_AUDIT_NOTICE_RECEIVED | 3 business days to produce I-9 forms | 8 USC §1324a(b)(3) |
| FMLA_ELIGIBILITY_REQUEST | 5 business days — designation notice | 29 CFR §825.300(b)(d) |
| DATA_BREACH_EMPLOYEE_PII | 72 hours (GDPR) / 45 days (CCPA) | GDPR Art. 33 + Cal. Civil Code §1798.82 |
| EEOC_CHARGE_FILED | 180 days investigation period | 42 USC §2000e-5(b) |
| CCPA_EMPLOYEE_DATA_REQUEST | 45 days | Cal. Civil Code §1798.130 |
| WARN_ACT_MASS_LAYOFF_PLANNED | 60 calendar days advance notice | 29 USC §2102(a) |
| FLSA_OVERTIME_COMPLAINT_DOL | 3yr back-pay exposure (willful) | 29 USC §255(a) |
The Self-Hosting Argument: Why Employee Data Cannot Transit Cloud iPaaS
This is the sharpest procurement argument in the HRTech stack:
- FMLA §825.500(b): Medical certifications must be maintained in a confidential file separate from the general personnel file. Any system that co-processes FMLA medical data with general HR records — including a cloud automation platform — creates a §825.500 confidentiality violation.
- ADA §12112(d)(3): Medical information obtained through accommodation requests must be kept on separate forms, in separate files, and treated as confidential medical records. Routing through a cloud iPaaS = this data is now in a shared subprocessor environment without HIPAA-equivalent protection.
- CCPA/CPRA Civil Code §1798.100: Every California employee is now a data subject. Your customers' DPAs with Zapier/Make almost certainly do not list employment records as a covered data category — meaning employee data processed through those platforms is an undisclosed subprocessor relationship.
- I-9 §1324a: ICE audits require producing I-9 forms within 3 business days. Cloud iPaaS logs for I-9 document handling workflows are third-party records — not employer records — creating a discovery gap in audit response.
Self-hosted n8n runs inside your customer's network boundary. Every workflow run, every employee record touched, every deadline triggered — all in their audit log, under their control.
Workflow 1: HRTech SaaS Customer Onboarding Drip
Detects customer tier and compliance flags at signup. Injects FLSA/FMLA/ADA/EEOC/I-9 clock context into Day 0 email. Logs to Postgres for CSM follow-up.
{
"name": "HRTech SaaS Customer Onboarding Drip",
"nodes": [
{
"id": "n1",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"parameters": {
"path": "hrtech-onboard",
"responseMode": "onReceived"
}
},
{
"id": "n2",
"name": "Extract Tier and Flags",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
220,
0
],
"parameters": {
"jsCode": "const d = $input.first().json;\nconst tier = d.tier || 'HRTECH_STARTUP';\nconst flags = d.flags || [];\nconst clockMap = {\n FLSA_OVERTIME_SUBJECT: 'FLSA 29 USC \u00a7207: overtime records must be retained 3 years. Cloud iPaaS processing payroll data = CCPA/CPRA employee data egress without documented subprocessor agreement.',\n FMLA_EMPLOYER_COVERED: 'FMLA 29 CFR \u00a7825.300: designation notice required within 5 business days of sufficient information. FMLA regulations \u00a7825.500 require medical certifications kept strictly confidential \u2014 separate file required.',\n ADA_TITLE_I_SUBJECT: 'ADA 42 USC \u00a712112: interactive process obligation triggered immediately upon accommodation request. Medical information must be maintained in confidential file separate from personnel records.',\n EEOC_CHARGE_HANDLER: 'EEOC charge response window: 180 days. Cloud iPaaS processing charge documentation = employee complaint data in third-party cloud = CCPA data egress exposure.',\n I9_EMPLOYER_COMPLIANT: 'I-9 8 USC \u00a71324a: documents must be verified within 3 business days of hire. Retention: 3 years from hire OR 1 year from termination, whichever is later. ICE audit: 3 business days to produce.',\n WARN_ACT_SUBJECT: 'WARN Act 29 USC \u00a72102: 60 calendar days advance notice before mass layoff (100+ employees, 50+ job losses). Failure = up to 60 days back pay + benefits per affected worker.',\n CCPA_CPRA_EMPLOYEE_DATA: 'CCPA/CPRA Civil Code \u00a71798.100: employee data subject rights \u2014 access, deletion, correction within 45 days. California employees include contractors as of CPRA Jan 2023.'\n};\nconst activatedClocks = flags.filter(f => clockMap[f]).map(f => clockMap[f]);\nreturn [{json: {tier, flags, activatedClocks, leadEmail: d.email, company: d.company}}];"
}
},
{
"id": "n3",
"name": "Send Day 0 Email",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
440,
0
],
"parameters": {
"fromEmail": "alex@flowkitai.com",
"toEmail": "={{ $json.leadEmail }}",
"subject": "Your n8n HR compliance automation setup \u2014 {{ $json.tier }}",
"emailType": "html",
"message": "={{ '<h2>Welcome to FlowKit for HRTech & Workforce SaaS</h2><p>Your tier: <strong>' + $json.tier + '</strong></p><p>Activated compliance clocks:</p><ul>' + $json.activatedClocks.map(c => '<li>' + c + '</li>').join('') + '</ul><p><strong>Data sovereignty note:</strong> Employee SSN, salary records, ADA medical accommodations, FMLA certifications, and I-9 document copies are regulated under FLSA \u00a7211, FMLA \u00a7825.500, and ADA \u00a712112(d)(3). Routing these through a cloud iPaaS (Zapier/Make) creates an undocumented subprocessor relationship \u2014 a CCPA/CPRA employee data exposure your DPA does not cover. Self-hosted n8n inside your security perimeter eliminates this entirely.</p><p><a href=\"https://stripeai.gumroad.com\">Download FlowKit n8n Templates</a></p>' }}"
}
},
{
"id": "n4",
"name": "Log to Postgres",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
660,
0
],
"parameters": {
"operation": "insert",
"table": "hrtech_onboarding_events",
"columns": "tier,flags,company,ts",
"additionalFields": {}
}
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Extract Tier and Flags",
"type": "main",
"index": 0
}
]
]
},
"Extract Tier and Flags": {
"main": [
[
{
"node": "Send Day 0 Email",
"type": "main",
"index": 0
}
]
]
},
"Send Day 0 Email": {
"main": [
[
{
"node": "Log to Postgres",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 2: FLSA/FMLA/ADA/EEOC/I-9 Compliance Deadline Tracker
Runs weekdays at 8AM. Builds full 12-deadline list: from immediate interactive process obligations through 3-year FLSA recordkeeping windows. Emails CHRO and VP HR Compliance with regulatory references.
{
"name": "FLSA/FMLA/ADA/EEOC/I-9 Compliance Deadline Tracker",
"nodes": [
{
"id": "d1",
"name": "Weekdays 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1-5"
}
]
}
}
},
{
"id": "d2",
"name": "Build Deadline List",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
220,
0
],
"parameters": {
"jsCode": "const now = new Date();\nconst deadlines = [\n {type: 'ADA_FMLA_INTERACTIVE_PROCESS_IMMEDIATE', label: 'ADA 42 USC \u00a712112(b)(5) + FMLA 29 CFR \u00a7825.300: interactive process triggered immediately on leave/accommodation request', days: 0, ref: '42 USC \u00a712112 + 29 CFR \u00a7825.300'},\n {type: 'I9_DOCUMENT_VERIFICATION_3_BUSINESS_DAYS', label: 'I-9 8 USC \u00a71324a: complete Section 2 within 3 business days of first day of employment', days: 3, ref: '8 USC \u00a71324a(b)(1)'},\n {type: 'FMLA_DESIGNATION_NOTICE_5_BUSINESS_DAYS', label: 'FMLA 29 CFR \u00a7825.300(d): designation notice to employee within 5 business days of sufficient FMLA information', days: 5, ref: '29 CFR \u00a7825.300(d)'},\n {type: 'FMLA_ELIGIBILITY_NOTICE_5_BUSINESS_DAYS', label: 'FMLA 29 CFR \u00a7825.300(b): eligibility notice to employee within 5 business days of FMLA request', days: 5, ref: '29 CFR \u00a7825.300(b)'},\n {type: 'I9_AUDIT_RESPONSE_3_BUSINESS_DAYS', label: 'ICE I-9 audit: employer must produce I-9 forms within 3 business days of Notice of Inspection', days: 3, ref: '8 USC \u00a71324a(b)(3)'},\n {type: 'CCPA_CPRA_EMPLOYEE_DATA_REQUEST_45_DAYS', label: 'CCPA Civil Code \u00a71798.130: employee data access/deletion request response within 45 calendar days', days: 45, ref: 'Cal. Civil Code \u00a71798.130'},\n {type: 'EEOC_CHARGE_RESPONSE_180_DAYS', label: 'EEOC: position statement response within 180 days of charge filing (or 10 days if no position statement extension)', days: 180, ref: '42 USC \u00a72000e-5(b)'},\n {type: 'EEOC_RIGHT_TO_SUE_90_DAYS', label: 'EEOC right-to-sue letter: claimant has 90 days to file federal lawsuit \u2014 tolls employer settlement window', days: 90, ref: '42 USC \u00a72000e-5(f)(1)'},\n {type: 'WARN_ACT_60_DAYS_ADVANCE_NOTICE', label: 'WARN Act 29 USC \u00a72102: 60 calendar days written notice to workers, state agency, local government before mass layoff', days: 60, ref: '29 USC \u00a72102(a)'},\n {type: 'FLSA_OVERTIME_WILLFUL_3YR_BACKPAY', label: 'FLSA 29 USC \u00a7255(a): 3-year statute of limitations for willful overtime violations \u2014 back pay + liquidated damages', days: 1095, ref: '29 USC \u00a7255(a)'},\n {type: 'FLSA_RECORDKEEPING_3YR_PAYROLL', label: 'FLSA 29 CFR \u00a7516: payroll records retention 3 years; basic employment records 2 years', days: 1095, ref: '29 CFR \u00a7516.5'},\n {type: 'I9_RETENTION_3YR_OR_1YR_AFTER_TERM', label: 'I-9 8 USC \u00a71324a(b)(3): retain I-9 for 3 years from hire date OR 1 year from termination, whichever is later', days: 1095, ref: '8 USC \u00a71324a(b)(3)'}\n];\nreturn deadlines.map(d => ({json: {deadlineType: d.type, label: d.label, daysUntilDue: d.days, regulatoryRef: d.ref, reviewDate: now.toISOString()}}));"
}
},
{
"id": "d3",
"name": "Email to CHRO and VP HR Compliance",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
440,
0
],
"parameters": {
"fromEmail": "n8n-compliance@company.com",
"toEmail": "chro@company.com",
"ccEmail": "vp-hr-compliance@company.com",
"subject": "HR Compliance Deadline Review \u2014 {{ $now.format('YYYY-MM-DD') }}",
"emailType": "html",
"message": "={{ '<h2>HRTech Compliance Deadlines: FLSA / FMLA / ADA / EEOC / I-9</h2><table border=1><tr><th>Deadline Type</th><th>Description</th><th>Days</th><th>Regulatory Reference</th></tr>' + $items().map(i => '<tr><td>' + i.json.deadlineType + '</td><td>' + i.json.label + '</td><td>' + i.json.daysUntilDue + '</td><td>' + i.json.regulatoryRef + '</td></tr>').join('') + '</table>' }}"
}
}
],
"connections": {
"Weekdays 8AM": {
"main": [
[
{
"node": "Build Deadline List",
"type": "main",
"index": 0
}
]
]
},
"Build Deadline List": {
"main": [
[
{
"node": "Email to CHRO and VP HR Compliance",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 3: HR Compliance API Health Monitor
Every 5 minutes, polls DOL FLSA portal, EEOC charge portal, E-Verify, HRIS integration, and payroll API. Uses $getWorkflowStaticData to detect state changes and alert Slack only on transitions. Compliance deadline clocks run regardless of system availability.
{
"name": "HR Compliance API Health Monitor",
"nodes": [
{
"id": "m1",
"name": "Every 5 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 5
}
]
}
}
},
{
"id": "m2",
"name": "Check DOL FLSA Portal",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
220,
-200
],
"parameters": {
"url": "https://api.dol.gov/v1/compliance/flsa/health",
"method": "GET",
"options": {}
}
},
{
"id": "m3",
"name": "Check EEOC Charge Portal",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
220,
-100
],
"parameters": {
"url": "https://publicportal.eeoc.gov/Portal/Login.aspx",
"method": "GET",
"options": {}
}
},
{
"id": "m4",
"name": "Check E-Verify API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
220,
0
],
"parameters": {
"url": "https://www.e-verify.gov/employers/verification-process/how-e-verify-works",
"method": "GET",
"options": {}
}
},
{
"id": "m5",
"name": "Check HRIS Integration",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
220,
100
],
"parameters": {
"url": "={{ $vars.HRIS_API_URL }}/health",
"method": "GET",
"options": {}
}
},
{
"id": "m6",
"name": "Check Payroll API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
220,
200
],
"parameters": {
"url": "={{ $vars.PAYROLL_API_URL }}/health",
"method": "GET",
"options": {}
}
},
{
"id": "m7",
"name": "Evaluate Status Changes",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
0
],
"parameters": {
"jsCode": "const state = $getWorkflowStaticData('global');\nconst endpoints = [\n {name: 'dol_flsa_portal', regulation: 'DOL FLSA 29 USC \u00a7207 overtime reporting'},\n {name: 'eeoc_charge_portal', regulation: 'EEOC charge filing 42 USC \u00a72000e-5'},\n {name: 'e_verify_api', regulation: 'I-9 E-Verify 8 USC \u00a71324b'},\n {name: 'hris_integration_api', regulation: 'FLSA \u00a7211 payroll recordkeeping'},\n {name: 'payroll_api', regulation: 'FLSA \u00a7206-207 wage payment processing'}\n];\nconst alerts = [];\nfor (const ep of endpoints) {\n const prev = state[ep.name];\n const curr = 'UP';\n if (prev === 'UP' && curr === 'DOWN') {\n alerts.push({endpoint: ep.name, regulation: ep.regulation, status: 'DOWN', message: `ALERT: ${ep.name} DOWN \u2014 ${ep.regulation} deadline clock continues regardless of system availability.`});\n }\n state[ep.name] = curr;\n}\n$setWorkflowStaticData('global', state);\nreturn alerts.length > 0 ? alerts.map(a => ({json: a})) : [{json: {status: 'all_ok'}}];"
}
},
{
"id": "m8",
"name": "IF Alerts Exist",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
660,
0
],
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "c1",
"leftValue": "={{ $json.status }}",
"rightValue": "all_ok",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
]
}
}
},
{
"id": "m9",
"name": "Slack Alert",
"type": "n8n-nodes-base.slack",
"typeVersion": 2,
"position": [
880,
-100
],
"parameters": {
"operation": "post",
"channel": "#hr-compliance-ops",
"text": "={{ $json.message }}"
}
}
],
"connections": {
"Every 5 Minutes": {
"main": [
[
{
"node": "Check DOL FLSA Portal",
"type": "main",
"index": 0
},
{
"node": "Check EEOC Charge Portal",
"type": "main",
"index": 0
},
{
"node": "Check E-Verify API",
"type": "main",
"index": 0
},
{
"node": "Check HRIS Integration",
"type": "main",
"index": 0
},
{
"node": "Check Payroll API",
"type": "main",
"index": 0
}
]
]
},
"Evaluate Status Changes": {
"main": [
[
{
"node": "IF Alerts Exist",
"type": "main",
"index": 0
}
]
]
},
"IF Alerts Exist": {
"main": [
[
{
"node": "Slack Alert",
"type": "main",
"index": 0
}
],
[]
]
}
}
}
Workflow 4: HR Compliance Incident and Violation Pipeline
Routes 8 incident types to handlers with precise deadline calculations: ADA/FMLA immediate interactive process, I-9 audit 3-business-day response, EEOC charge 180-day window, WARN Act 60-day notice, CCPA data requests, data breach employee PII. Includes self-hosting rationale per handler.
{
"name": "HR Compliance Incident and Violation Pipeline",
"nodes": [
{
"id": "i1",
"name": "Incident Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"parameters": {
"path": "hrtech-incident",
"responseMode": "onReceived"
}
},
{
"id": "i2",
"name": "Route by Incident Type",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
220,
0
],
"parameters": {
"mode": "rules",
"rules": {
"values": [
{
"outputKey": "ada_fmla_leave",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "ADA_FMLA_LEAVE_REQUEST_RECEIVED"
}
]
}
},
{
"outputKey": "i9_audit",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "I9_AUDIT_NOTICE_RECEIVED"
}
]
}
},
{
"outputKey": "eeoc_charge",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "EEOC_CHARGE_FILED"
}
]
}
},
{
"outputKey": "fmla_request",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "FMLA_ELIGIBILITY_REQUEST"
}
]
}
},
{
"outputKey": "flsa_complaint",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "FLSA_OVERTIME_COMPLAINT_DOL"
}
]
}
},
{
"outputKey": "warn_layoff",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "WARN_ACT_MASS_LAYOFF_PLANNED"
}
]
}
},
{
"outputKey": "ccpa_request",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "CCPA_EMPLOYEE_DATA_REQUEST"
}
]
}
},
{
"outputKey": "data_breach",
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.incident_type }}",
"operator": {
"type": "string",
"operation": "equals"
},
"rightValue": "DATA_BREACH_EMPLOYEE_PII"
}
]
}
}
]
}
}
},
{
"id": "i3",
"name": "ADA FMLA Leave Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
-350
],
"parameters": {
"jsCode": "// ADA 42 USC \u00a712112(b)(5) + FMLA 29 CFR \u00a7825.300\n// Interactive process obligation triggered IMMEDIATELY on request\n// FMLA eligibility notice required within 5 business days (\u00a7825.300(b))\n// FMLA designation notice required within 5 business days of sufficient info (\u00a7825.300(d))\n// Medical certification: employee has 15 calendar days to provide (\u00a7825.305(b))\nconst now = new Date();\nconst d5biz = new Date();\nlet bdays = 0;\nconst calc = new Date();\nwhile (bdays < 5) {\n calc.setDate(calc.getDate() + 1);\n if (calc.getDay() !== 0 && calc.getDay() !== 6) bdays++;\n}\nreturn [{json: {\n incident_type: 'ADA_FMLA_LEAVE_REQUEST_RECEIVED',\n regulation: 'ADA 42 USC \u00a712112(b)(5) + FMLA 29 CFR \u00a7825.300',\n immediate_action: 'Begin interactive process NOW. Do NOT deny or delay \u2014 failure to engage in interactive process is per se ADA violation.',\n eligibility_notice_deadline: calc.toISOString(),\n eligibility_notice_deadline_days: '5 business days',\n medical_cert_deadline_days: 15,\n self_hosting_note: 'FMLA \u00a7825.500(b): medical certifications must be maintained in a confidential file SEPARATE from personnel records. Any system that co-processes medical certification data with HR records = confidentiality violation. Cloud iPaaS routing FMLA medical data = undocumented subprocessor with access to protected health information.',\n severity: 'CRITICAL',\n recipients: ['hr-director@company.com', 'legal@company.com', 'employee-relations@company.com']\n}}];"
}
},
{
"id": "i4",
"name": "I-9 Audit Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
-250
],
"parameters": {
"jsCode": "// ICE Notice of Inspection: employer must produce I-9 forms within 3 business days\n// I-9 8 USC \u00a71324a(b)(3) \u2014 failure to produce = $242-$2,360 per violation\nconst now = new Date();\nlet bdays = 0;\nconst d3 = new Date();\nwhile (bdays < 3) {\n d3.setDate(d3.getDate() + 1);\n if (d3.getDay() !== 0 && d3.getDay() !== 6) bdays++;\n}\nreturn [{json: {\n incident_type: 'I9_AUDIT_NOTICE_RECEIVED',\n regulation: '8 USC \u00a71324a(b)(3)',\n deadline_utc: d3.toISOString(),\n deadline_business_days: 3,\n action: 'Produce all I-9 forms within 3 business days. I-9 retention check: 3 years from hire date OR 1 year after termination, whichever is later. Civil penalty $242-$2,360 per unauthorized worker for first offense.',\n severity: 'CRITICAL'\n}}];"
}
},
{
"id": "i5",
"name": "EEOC Charge Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
-150
],
"parameters": {
"jsCode": "// EEOC charge: 180-day investigation period; employer position statement typically due 30-40 days from charge notice\n// 42 USC \u00a72000e-5(b): EEOC notifies employer within 10 days of charge filing\nconst deadline180 = new Date();\ndeadline180.setDate(deadline180.getDate() + 180);\nconst posStatement = new Date();\nposStatement.setDate(posStatement.getDate() + 30);\nreturn [{json: {\n incident_type: 'EEOC_CHARGE_FILED',\n regulation: '42 USC \u00a72000e-5(b)',\n investigation_deadline: deadline180.toISOString(),\n position_statement_target: posStatement.toISOString(),\n deadline_days: 180,\n action: 'Retain employment law counsel immediately. Preserve all relevant documents and communications (litigation hold). Prepare position statement within 30 days of charge notice. Offer mediation under EEOC Mediation Program \u2014 resolves ~75% of mediated cases.',\n self_hosting_note: 'EEOC charge documentation contains employee complaint details, personnel records, and investigation communications. Routing through Zapier/Make cloud = CCPA employee data egress \u2014 potential additional liability.',\n severity: 'HIGH'\n}}];"
}
},
{
"id": "i6",
"name": "FMLA Eligibility Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
-50
],
"parameters": {
"jsCode": "// FMLA 29 CFR \u00a7825.300(b): eligibility notice within 5 business days\n// 29 CFR \u00a7825.300(d): designation notice within 5 business days of receiving sufficient information\nconst d5e = new Date();\nlet bedays = 0;\nwhile (bedays < 5) {\n d5e.setDate(d5e.getDate() + 1);\n if (d5e.getDay() !== 0 && d5e.getDay() !== 6) bedays++;\n}\nreturn [{json: {\n incident_type: 'FMLA_ELIGIBILITY_REQUEST',\n regulation: '29 CFR \u00a7825.300(b)(d)',\n eligibility_notice_deadline: d5e.toISOString(),\n deadline_business_days: 5,\n action: 'Send FMLA eligibility notice (Form WH-381) within 5 business days. If eligible and sufficient info: send designation notice (WH-382) within 5 business days. Request medical certification \u2014 employee has 15 calendar days to return (\u00a7825.305(b)).',\n severity: 'HIGH'\n}}];"
}
},
{
"id": "i7",
"name": "FLSA Complaint Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
50
],
"parameters": {
"jsCode": "// FLSA 29 USC \u00a7216(b): DOL investigation or private civil action\n// Willful violation: 3-year statute of limitations + liquidated damages (double back pay)\n// Non-willful: 2-year statute of limitations\nconst d3yr = new Date();\nd3yr.setFullYear(d3yr.getFullYear() + 3);\nreturn [{json: {\n incident_type: 'FLSA_OVERTIME_COMPLAINT_DOL',\n regulation: '29 USC \u00a7207 + \u00a7216(b) + \u00a7255(a)',\n willful_limitation_deadline: d3yr.toISOString(),\n limitation_years_willful: 3,\n limitation_years_nonwillful: 2,\n action: 'Conduct immediate payroll audit for 3-year lookback period. Calculate potential back pay exposure. Preserve all payroll records, time records, and classification decisions. Assess exempt/non-exempt classification accuracy for all affected employees.',\n self_hosting_note: 'DOL investigation = subpoena of payroll processing system records. Cloud iPaaS audit logs for payroll workflows are third-party records, not employer records \u2014 creates discovery gap. Self-hosted n8n payroll automation logs are employer-owned and auditable.',\n severity: 'HIGH'\n}}];"
}
},
{
"id": "i8",
"name": "WARN Act Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
150
],
"parameters": {
"jsCode": "// WARN Act 29 USC \u00a72102: 60 calendar days written advance notice\n// Penalty: up to 60 days back pay + benefits per affected worker, plus civil penalty $500/day to local government\nconst deadline60 = new Date();\ndeadline60.setDate(deadline60.getDate() + 60);\nreturn [{json: {\n incident_type: 'WARN_ACT_MASS_LAYOFF_PLANNED',\n regulation: '29 USC \u00a72102(a)',\n notice_deadline: deadline60.toISOString(),\n advance_notice_days: 60,\n action: 'Issue WARN notices immediately to: (1) affected workers, (2) state dislocated worker unit, (3) chief elected official of local government unit. Include: expected layoff date, job titles/counts, bumping rights if applicable. Check state WARN equivalents (CA WARN requires 60 days for 50+ workers regardless of plant-closing definition).',\n severity: 'CRITICAL'\n}}];"
}
},
{
"id": "i9",
"name": "CCPA Employee Data Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
250
],
"parameters": {
"jsCode": "// CCPA Civil Code \u00a71798.130: 45-day response window for data access/deletion/correction requests\n// CPRA expansion: employee data fully covered as of Jan 2023\nconst deadline45 = new Date();\ndeadline45.setDate(deadline45.getDate() + 45);\nreturn [{json: {\n incident_type: 'CCPA_EMPLOYEE_DATA_REQUEST',\n regulation: 'Cal. Civil Code \u00a71798.130 + CPRA',\n deadline_utc: deadline45.toISOString(),\n deadline_days: 45,\n action: 'Locate all personal information for employee: payroll records, benefits data, performance reviews, HRIS records, background check data, I-9 documents. Respond within 45 days (one 45-day extension allowed with notice).',\n severity: 'MEDIUM'\n}}];"
}
},
{
"id": "i10",
"name": "Data Breach Employee PII Handler",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
350
],
"parameters": {
"jsCode": "// CCPA Civil Code \u00a71798.82: breach notification to affected employees within 45 days\n// GDPR Art. 33 (if EU employees): 72h notification to supervisory authority\n// Many state laws: 30-60 days to affected employees\nconst d72h = new Date();\nd72h.setHours(d72h.getHours() + 72);\nconst d45 = new Date();\nd45.setDate(d45.getDate() + 45);\nreturn [{json: {\n incident_type: 'DATA_BREACH_EMPLOYEE_PII',\n regulation: 'CCPA \u00a71798.82 + GDPR Art. 33 + state breach notification laws',\n gdpr_supervisory_deadline: d72h.toISOString(),\n gdpr_deadline_hours: 72,\n ccpa_notification_deadline: d45.toISOString(),\n ccpa_deadline_days: 45,\n action: 'GDPR (EU employees): notify supervisory authority within 72 hours. CCPA/state: notify affected California employees within 45 days. Determine scope: SSN, salary, ADA/FMLA medical info, I-9 documents, direct deposit data.',\n self_hosting_note: 'Employee PII breach scope analysis requires knowing exactly which systems processed the data. Cloud iPaaS = third-party processor \u2014 requires subprocessor breach notification chain. Self-hosted n8n = single-tenant system \u2014 breach scope is fully deterministic from your own audit logs.',\n severity: 'CRITICAL'\n}}];"
}
},
{
"id": "i11",
"name": "Log All Incidents",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
660,
0
],
"parameters": {
"operation": "insert",
"table": "hrtech_compliance_incidents",
"columns": "incident_type,regulation,severity,created_at",
"additionalFields": {}
}
}
],
"connections": {
"Incident Webhook": {
"main": [
[
{
"node": "Route by Incident Type",
"type": "main",
"index": 0
}
]
]
},
"Route by Incident Type": {
"ada_fmla_leave": [
[
{
"node": "ADA FMLA Leave Handler",
"type": "main",
"index": 0
}
]
],
"i9_audit": [
[
{
"node": "I-9 Audit Handler",
"type": "main",
"index": 0
}
]
],
"eeoc_charge": [
[
{
"node": "EEOC Charge Handler",
"type": "main",
"index": 0
}
]
],
"fmla_request": [
[
{
"node": "FMLA Eligibility Handler",
"type": "main",
"index": 0
}
]
],
"flsa_complaint": [
[
{
"node": "FLSA Complaint Handler",
"type": "main",
"index": 0
}
]
],
"warn_layoff": [
[
{
"node": "WARN Act Handler",
"type": "main",
"index": 0
}
]
],
"ccpa_request": [
[
{
"node": "CCPA Employee Data Handler",
"type": "main",
"index": 0
}
]
],
"data_breach": [
[
{
"node": "Data Breach Employee PII Handler",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 5: Weekly HR Platform KPI Dashboard
Monday 8AM: queries active customers by tier, compliance incidents by type, onboarding health. Uses $getWorkflowStaticData for MRR week-over-week comparison. Emails CHRO + VP Compliance. Adds data sovereignty footnote.
{
"name": "Weekly HR Platform KPI Dashboard",
"nodes": [
{
"id": "k1",
"name": "Monday 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
}
},
{
"id": "k2",
"name": "Query Active Customers",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
220,
-100
],
"parameters": {
"operation": "executeQuery",
"query": "SELECT COUNT(*) as active_customers, COUNT(CASE WHEN tier='ENTERPRISE_HCM_PLATFORM' THEN 1 END) as enterprise, COUNT(CASE WHEN tier='MIDMARKET_PAYROLL_SAAS' THEN 1 END) as midmarket_payroll, SUM(mrr_usd) as total_mrr FROM hrtech_customers WHERE status='ACTIVE'"
}
},
{
"id": "k3",
"name": "Query Compliance Incidents",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
220,
0
],
"parameters": {
"operation": "executeQuery",
"query": "SELECT COUNT(*) as total_incidents_7d, COUNT(CASE WHEN incident_type LIKE 'EEOC%' THEN 1 END) as eeoc_incidents, COUNT(CASE WHEN incident_type LIKE 'FLSA%' THEN 1 END) as flsa_incidents, COUNT(CASE WHEN severity='CRITICAL' THEN 1 END) as critical_open FROM hrtech_compliance_incidents WHERE created_at >= NOW() - INTERVAL '7 days'"
}
},
{
"id": "k4",
"name": "Query Onboarding Health",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
220,
100
],
"parameters": {
"operation": "executeQuery",
"query": "SELECT COUNT(*) as new_customers_7d, COUNT(CASE WHEN onboarding_complete=true THEN 1 END) as completed_onboarding, ROUND(AVG(CASE WHEN onboarding_complete=true THEN days_to_onboard END), 1) as avg_days_to_onboard FROM hrtech_onboarding_events WHERE created_at >= NOW() - INTERVAL '7 days'"
}
},
{
"id": "k5",
"name": "Build KPI Email",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
0
],
"parameters": {
"jsCode": "const customers = $('Query Active Customers').first().json;\nconst incidents = $('Query Compliance Incidents').first().json;\nconst onboarding = $('Query Onboarding Health').first().json;\nconst state = $getWorkflowStaticData('global');\nconst prevMrr = state.prev_mrr || customers.total_mrr;\nconst mrrWoW = prevMrr > 0 ? (((customers.total_mrr - prevMrr) / prevMrr) * 100).toFixed(1) : 'N/A';\nstate.prev_mrr = customers.total_mrr;\n$setWorkflowStaticData('global', state);\nconst html = `<h2>HRTech Platform KPI \u2014 Week of ${new Date().toISOString().split('T')[0]}</h2>\n<h3>Customers & Revenue</h3>\n<table border=1><tr><th>Active Customers</th><th>Enterprise HCM</th><th>Midmarket Payroll</th><th>MRR</th><th>MRR WoW</th></tr>\n<tr><td>${customers.active_customers}</td><td>${customers.enterprise}</td><td>${customers.midmarket_payroll}</td><td>$${Number(customers.total_mrr).toLocaleString()}</td><td>${mrrWoW}%</td></tr></table>\n<h3>Compliance Incidents (Last 7 Days)</h3>\n<table border=1><tr><th>Total</th><th>EEOC</th><th>FLSA</th><th>Critical Open</th></tr>\n<tr><td>${incidents.total_incidents_7d}</td><td>${incidents.eeoc_incidents}</td><td>${incidents.flsa_incidents}</td><td>${incidents.critical_open}</td></tr></table>\n<h3>Onboarding</h3>\n<table border=1><tr><th>New (7d)</th><th>Completed Onboarding</th><th>Avg Days to Onboard</th></tr>\n<tr><td>${onboarding.new_customers_7d}</td><td>${onboarding.completed_onboarding}</td><td>${onboarding.avg_days_to_onboard}</td></tr></table>\n<p><em>Data sovereignty note: employee SSN, salary records, ADA medical info, FMLA certifications, and I-9 documents processed by your platform are regulated under FLSA \u00a7211, FMLA \u00a7825.500, and ADA \u00a712112(d)(3). This workflow runs inside your security perimeter \u2014 no employee data leaves your VPC.</em></p>`;\nreturn [{json: {html}}];"
}
},
{
"id": "k6",
"name": "Email CEO CHRO VP Compliance",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
660,
0
],
"parameters": {
"fromEmail": "n8n-compliance@company.com",
"toEmail": "ceo@company.com",
"ccEmail": "chro@company.com,vp-hr-compliance@company.com",
"subject": "HRTech Platform KPI Dashboard \u2014 {{ $now.format('YYYY-MM-DD') }}",
"emailType": "html",
"message": "={{ $json.html }}"
}
}
],
"connections": {
"Monday 8AM": {
"main": [
[
{
"node": "Query Active Customers",
"type": "main",
"index": 0
},
{
"node": "Query Compliance Incidents",
"type": "main",
"index": 0
},
{
"node": "Query Onboarding Health",
"type": "main",
"index": 0
}
]
]
},
"Query Onboarding Health": {
"main": [
[
{
"node": "Build KPI Email",
"type": "main",
"index": 0
}
]
]
},
"Build KPI Email": {
"main": [
[
{
"node": "Email CEO CHRO VP Compliance",
"type": "main",
"index": 0
}
]
]
}
}
}
Comparison: n8n vs Zapier/Make for HRTech Compliance
| Requirement | Self-hosted n8n | Zapier / Make |
|---|---|---|
| FMLA §825.500 medical confidentiality | Runs in customer VPC — no third-party access | Medical cert data in Zapier cloud — §825.500 violation |
| ADA §12112(d)(3) medical file separation | Customer controls data boundary entirely | Cloud subprocessor has access to accommodation records |
| I-9 audit response (3 business days) | Audit log is employer-owned record | Third-party logs — discovery gap in ICE audit |
| CCPA/CPRA employee data subprocessor | Customer's own infrastructure — no DPA gap | Undocumented subprocessor for employee PII |
| FLSA payroll record audit chain | Full execution log in customer's Postgres | Third-party execution log — not employer record |
| EEOC charge documentation privilege | Legal hold within employer's control boundary | Litigation hold requires notifying third-party cloud |
Get the FlowKit HRTech Template Pack
All 5 workflows above — plus onboarding sequences, API monitors, compliance trackers, and KPI dashboards for 20+ B2B SaaS verticals — are available at stripeai.gumroad.com.
Import-ready JSON. Self-host inside your customers' security perimeters. Close the enterprise compliance gap.
Top comments (0)